Trabajo elaborado para la asignatura “Programación y manejo de datos en la era del Big Data” de la Universitat de València durante el curso 2021-2022. El repo del trabajo está aquí.

La página web de la asignatura y los trabajos de mis compañeros pueden verse aquí.


1. Introducción

La Formula 1 es uno de los deportes/espectaculos más importantes del mundo, logrando a lo largo de sus historia captar a millones y millones de espectadores. Nuetro trabajo pretende plasmar la grandeza de la Fórmula 1 a través de distintos datos que pueden verse a lo largo del trabajo, tanto presentes como pasados. Además, parte del trabajo se ha centrado en la figura de Fernando Alonso, el piloto con mayor importancia en España, y uno de los más relevantes en la historia de la Formula 1.
En relación con la asignatura, la elección del tema se debe a lo fundamental que son los datos en este deporte, tanto para la elaboración de estrategias, el diseño de los coches o incluso de las pistas. Debido a todas estas razones, creemos que la F1, a pesar de no ser un tema relacionado con la economía, encaja perfectamente con la asignatura.

THE PLAN

2. Datos

Hemos encontrado en kaggle bastantes conjuntos de datos con los que poder trabajar, pero especialmente este, que posee gran variedad de datos en lo referente a pilotos, resultados, circuitos, tiempos, etc.

2.1. Procesando los datos

A continuación se muestra toda la manipulación de los datos, a partir del conjunto de datos mostrado anteriormente, y que posteriormente son utilizados para la realización de los distintas partes que forman el trabajo.


#---PREPARACION DE LOS DATOS
tiempos <- rio::import(file = "./datos/lap_times.csv")
pilotos <- rio::import(file = "./datos/drivers.csv")
resultados <- rio::import(file = "./datos/results.csv")
carreras <- rio::import(file = "./datos/races.csv")
escuderias <- rio::import(file = "./datos/constructors.csv")
escuderias2 <- rio::import(file = "./datos/constructor_standings.csv")
result_escuderias <- rio::import(file = "./datos/constructor_results.csv")
circuitos <- rio::import(file = "./datos/circuits.csv")

#----------------------------------------
#capitulo oscuro del deporte
#creo df de muertes de formula 1
muertesf1 <- data.frame(
  "orden" = 1:42,
  "driverRef" = c("Chet Miller", "Carl Scaraborough", "Onofre Marimon", "Manny Ayulo", "Bill Vukovich", "Alberto Ascari","Eugenio Castellotti", "Keith Andrews", "Pat O'Connor", "Luigi Musso", "Peter Collins", "Stuart Lewis-Evans", "Jerry Unser", "Bob Cortner", "Ivor Bueb", "Chris Bristow", "Alan Stacey", "Giulio Cabianca", "Wolfgang von Trips", "Carel Godin de Beaufort", "John Taylor", "Lorenzo Bandini", "Bob Anderson", "Jo Schlesser", "Gerhard Mitter", "Piers Courage", "Jochen Rindt", "Jo Siffert", "Roger Williamson", "François Cevert", "Peter Revson", "Helmuth Koinigg", "Mark Donohue", "Tom Pryce", "Ronnie Peterson", "Patrick Depailler", "Gilles Villeneuve", "Riccardo Paletti", "Elio de Angelis", "Roland Ratzenberger", "Ayrton Senna", "Jules Bianchi"),
  "nationality" = c("American", "American", "Argentine", "American", "American", "Italian","Italian", "American", "American", "Italian", "British", "British", "American", "American", "British", "British", "British", "Italian", "German", "Dutch", "British", "Italian" , "British", "French", "German", "British", "Austrian", "Swiss", "British", "French", "American", "Austrian", "American", "British", "Swedish", "French", "Canadian", "Italian", "Italian", "Austrian", "Brazilian", "French"),
  "fecha_muerte" = c(1953, 1953, 1954, 1955, 1955, 1955, 1957, 1957, 1958,1958,1958,1958,1959,1959,1959,1960, 1960,1961,1961,1964,1966, 1967, 1967,1968,1969, 1970,1970,1971,1973,1973,1974,1974,1975,1977,1978,1980,1982,1982,1986,1994,1994,2014))
#no pongo las comillas en los años para que se creen directamente como observaciones numericas

#creo un df con todos los años para luego fusionarlo, ya que no hay muertes todos los años 
anyos <- data.frame(
  "orden" = 1:71,
  "año" = c(1950:2020))

#sumatorio de las muertes por año
muertes_anyo <- muertesf1 %>% group_by(fecha_muerte) %>% mutate(muertesxanyo = sum(n())) %>% distinct(fecha_muerte, muertesxanyo) 

#fusiono los 2 dfs para que tenga en cuenta los años donde no hay muertes
muertesf1_final <- full_join(muertes_anyo, anyos, c("fecha_muerte" = "año")) %>% select(fecha_muerte,muertesxanyo) %>% arrange(fecha_muerte)

#convierto los N/A en 0, es decir, cuando no hay observaciones, ha habido 0 muertes
muertesf1_final[is.na(muertesf1_final)] <- 0

#------------------------------------------------
#str(resultados)
#str(pilotos)
#pilotos[, c(1)] <- sapply(pilotos[, c(1)], as.numeric)
#resultados[, c(3,6,9)] <- sapply(resultados[, c(3,6,9)], as.numeric)

#----------------------------------------------------------------------------------

#numero de carreras que ha corrido cada piloto

n_carreras <- resultados %>% group_by(driverId) %>% mutate(numero_carreras = sum(n())) %>% distinct(numero_carreras) %>% arrange(desc(numero_carreras)) 

n_carreras_nom <- full_join(n_carreras, pilotos, c ("driverId" = "driverId")) %>% select(driverId, driverRef, numero_carreras)  %>%  filter(numero_carreras >= 202 ) #los 20 qque mas carreras tienen (no funciona usar slice_max)

#--------------------------------------------------------------------------------
#nacionalidad de los pilotos a lo largo de la historia 
#mapa
nacionalidad <- pilotos %>% group_by(nationality) %>% mutate(numero_compatriotas = sum(n())) %>% distinct(numero_compatriotas) %>% arrange(desc(numero_compatriotas)) %>% 
  str_replace_all(., "British", "United Kingdom") %>% 
  str_replace_all(., "American", "United States") %>% 
  str_replace_all(., "Italian", 'Italy') %>% 
  str_replace_all(., "French" , 'France') %>% 
  str_replace_all(., "German" , 'Germany') %>% 
  str_replace_all(., "Brazilian" , 'Brazil') %>% 
  str_replace_all(., "Argentine" , 'Argentina') %>% 
  str_replace_all(., "Swiss" , 'Switzerland') %>% 
  str_replace_all(., "Belgian" , 'Belgium') %>% 
  str_replace_all(., "South African" , 'South Africa') %>% 
  str_replace_all(., "Japanese" , 'Japan') %>% 
  str_replace_all(., "Australian" , 'Australia') %>%
  str_replace_all(., "Dutch" , 'Netherlands') %>%
  str_replace_all(., "Spanish" , 'Spain') %>%
  str_replace_all(., "Austrian" , 'Austria') %>%
  str_replace_all(., "Canadian" , 'Canada') %>%
  str_replace_all(., "Swedish" , 'Sweden') %>%
  str_replace_all(., "Finnish" , 'Finland') %>%
  str_replace_all(., "New Zealander" , 'New Zealand') %>%
  str_replace_all(., "Mexican" , 'Mexico') %>%
  str_replace_all(., "Irish" , 'Ireland') %>%
  str_replace_all(., "Danish" , 'Denmark') %>%
  str_replace_all(., "Portuguese" , 'Portugal') %>%
  str_replace_all(., "Monegasque" , 'France') %>%
  str_replace_all(., "Rhodesian" , 'Zimbabwe') %>%
  str_replace_all(., "Uruguayan" , 'Uruguay') %>%
  str_replace_all(., "Russian" , 'Russia') %>%
  str_replace_all(., "Colombian" , 'Colombia') %>%
  str_replace_all(., "Venezuelan" , 'Venezuela') %>%
  str_replace_all(., "East German" , 'German') %>%
  str_replace_all(., "Indian" , 'India') %>%
  str_replace_all(., "Thai" , 'Thailand') %>%
  str_replace_all(., "Polish" , 'Poland') %>%
  str_replace_all(., "Monegasque" , 'France') %>%
  str_replace_all(., "Hungarian" , 'Hungary') %>%
  str_replace_all(., "Czech" , 'Czech Rep.') %>%
  str_replace_all(., "Malaysian" , 'Malaysia') %>%
  str_replace_all(., "Chilean" , 'Chile') %>%
  str_replace_all(., "Liechtensteiner" , 'Switzerland') %>%
  str_replace_all(., "American-Italian" , 'United States') %>%
  str_replace_all(., "Argentine-Italian" , 'Argentina') %>%
  str_replace_all(., "Indonesian" , 'Indonesia')

paises_normales <- c("United Kingdom", "United States", "Italy", "France", "Germany", "Brazil", "Argentina", "Switzerland", "Belgium", "South Africa", "Japan", "Australia", "Netherlands", "Spain", "Austria", "Canada", "Sweden", "Finland", "New Zealand", "Mexico", "Ireland", "Denmark", "Portugal", "France", "Zimbabwe", "Uruguay", "Russia", "Colombia", "Venezuela", "Germany", "India", "Thailand", "Poland", "Hungary", "Czech Rep.", "Malaysia", "Chile", "Switzerland", "United States", "Argentina", "Indonesia" )

nacionalidad <- pilotos %>% group_by(nationality) %>% 
  mutate(numero_compatriotas = sum(n())) %>% 
  distinct(numero_compatriotas) %>% 
  arrange(desc(numero_compatriotas)) %>% 
  add_column(paises_normales) %>%  
  group_by(paises_normales) %>% 
  mutate(total_pilotos = sum(numero_compatriotas)) %>%  
  distinct(paises_normales, total_pilotos)

data(World)
world <- World; rm(World)

world <- world[!(world$name %in% c('Greenland', 'Antarctica')),]

pilotos_por_paises <- full_join(nacionalidad, world, c( "paises_normales" = "name")) 

pilotos_por_paises$country <- NULL

pilotos_por_paises[is.na(pilotos_por_paises)] <- 0

gg_pilotos_por_paises <- ggplot(data = pilotos_por_paises, aes(geometry = geometry)) + geom_sf() +
       labs(title = "Pilotos por país",
            caption = "Menor intensidad de color en aquellos paises con más pilotos")

gg_pilotos_por_paises <- gg_pilotos_por_paises + 
  geom_sf(aes(fill = total_pilotos)) + 
  theme(plot.subtitle = element_text(colour = "white"),
    plot.caption = element_text(colour = "white"),
    axis.ticks = element_line(linetype = "blank"),
    panel.grid.major = element_line(linetype = "blank"),
    panel.grid.minor = element_line(linetype = "blank"),
    axis.text = element_text(colour = "gray13"),
    plot.title = element_text(size = 20,
        colour = "white", hjust = 0.5), legend.text = element_text(colour = "white"),
    legend.title = element_text(colour = "white"),
    panel.background = element_rect(fill = "gray13"),
    plot.background = element_rect(fill = "gray13"),
    legend.background = element_rect(fill = "gray13")) +labs(fill = "Nª de pilotos") + theme(panel.background = element_rect(colour = "gray13"),
    plot.background = element_rect(colour = "gray13")) + theme(panel.grid.major = element_line(colour = NA),
    panel.background = element_rect(linetype = "solid"),
    plot.background = element_rect(linetype = "solid")) + scale_fill_gradient2(low = "white", mid = "pink", high = "red", midpoint = .02)

#------------------------------------------------------------------------------
# numero de victorias por piloto
victorias <- resultados %>% filter(position == "1") %>% 
  group_by(driverId) %>% 
  mutate(n_victorias = sum(n())) %>% 
  distinct(n_victorias) %>% 
  arrange(desc(n_victorias))

#aqui fusiono con el df de pilotos para que aparezca el nombre y no sólo el ID del piloto en cuestion, y hago lo mismo que en el apartado de arriba para ordenar
victorias_con_nombre <- full_join(victorias, pilotos, c ("driverId" = "driverId")) %>% 
  select(driverId, nationality, driverRef, n_victorias)  
mas_victorias <- victorias_con_nombre %>%  filter(n_victorias >= 25 ) 

#victorias 2
victorias2 <- full_join(pilotos, resultados, c("driverId" = "driverId")) %>% 
  full_join(., carreras, c("raceId" = "raceId")) %>% 
  select(driverId, driverRef, position, year, date) %>% 
  filter(position == 1) %>% 
  group_by(driverRef) %>% 
  mutate(victoria_num = sum( NN = n())) %>% 
  filter(victoria_num >= 20) %>% 
  arrange(victoria_num, date) %>% 
  mutate( suma_vic = cumsum(position))

#-------------------------------------------------

#resultado medio

resultados[, c(7)] <- sapply(resultados[, c(7)], as.numeric)
resultados[is.na(resultados)] <- 25 

#resultado_medio <-  full_join(pilotos, resultados,  c ("driverId" = "driverId")) %>% 
#select(driverId, driverRef, position) %>% 
 # group_by(driverId) %>% 
  #mutate(result_medio = mean(position)) %>% 
  #distinct (driverId, driverRef, result_medio) %>% arrange(result_medio)

#resultado medio en clasificacion
resultado_medio_clas <-  full_join(pilotos, resultados,  c ("driverId" = "driverId")) %>% 
  select(driverId, driverRef, grid) %>% 
  group_by(driverId) %>% 
  mutate(result_medio_clas = mean(grid)) %>% 
  distinct (driverId, driverRef, result_medio_clas)  %>% 
  filter(result_medio_clas > 0) %>% 
  arrange(result_medio_clas)  


#numero de vueltas liderando


#puntos por carrera (puntos/carrera)

puntos_x_carrera <-  full_join(pilotos, resultados,  c ("driverId" = "driverId")) %>% select(driverId, driverRef, points) %>% full_join(., n_carreras,  c ("driverId" = "driverId")) %>% group_by(driverId) %>% mutate(total_puntos = sum(points)) %>% distinct(driverId, driverRef, numero_carreras, total_puntos) %>% mutate(media_puntos = total_puntos/numero_carreras) %>% arrange(desc(media_puntos))

#-------------------------------
#remontadas

#mas posiciones remontadas en una carrera gran premio


resultados[, c(6,9)] <- sapply(resultados[, c(6,9)], as.numeric) #transformo variables grid y positionOrder en numerico
str(resultados) # para comprobarlo
#> 'data.frame':    25140 obs. of  18 variables:
#>  $ resultId       : int  1 2 3 4 5 6 7 8 9 10 ...
#>  $ raceId         : int  18 18 18 18 18 18 18 18 18 18 ...
#>  $ driverId       : int  1 2 3 4 5 6 7 8 9 10 ...
#>  $ constructorId  : int  1 2 3 4 1 3 5 6 2 7 ...
#>  $ number         : chr  "22" "3" "7" "5" ...
#>  $ grid           : num  1 5 7 11 3 13 17 15 2 18 ...
#>  $ position       : num  1 2 3 4 5 6 7 8 25 25 ...
#>  $ positionText   : chr  "1" "2" "3" "4" ...
#>  $ positionOrder  : num  1 2 3 4 5 6 7 8 9 10 ...
#>  $ points         : num  10 8 6 5 4 3 2 1 0 0 ...
#>  $ laps           : int  58 58 58 58 58 57 55 53 47 43 ...
#>  $ time           : chr  "1:34:50.616" "+5.478" "+8.163" "+17.181" ...
#>  $ milliseconds   : chr  "5690616" "5696094" "5698779" "5707797" ...
#>  $ fastestLap     : chr  "39" "41" "41" "58" ...
#>  $ rank           : chr  "2" "3" "5" "7" ...
#>  $ fastestLapTime : chr  "1:27.452" "1:27.739" "1:28.090" "1:28.603" ...
#>  $ fastestLapSpeed: chr  "218.300" "217.586" "216.719" "215.464" ...
#>  $ statusId       : int  1 1 1 1 1 11 5 5 4 3 ...


#mayores remontadas de la historia, se resta posicion de salida - posicion final
puestos_remontados <- resultados %>% mutate(remontados = grid - positionOrder) %>% 
  select(raceId, driverId, grid, positionOrder, remontados) 


#de toda la historia
circuitos_gp <- full_join(carreras, circuitos, c("circuitId" = "circuitId")) %>% 
  select(circuitId, name.y, raceId, year)

ptos_remont_carrera <- inner_join(puestos_remontados, circuitos_gp)

puestos_remont_piloto <- full_join(pilotos, ptos_remont_carrera, c("driverId" = "driverId")) %>% 
  slice_max(remontados, n=10) %>% 
  select(driverId, driverRef,name.y,year, raceId, grid, positionOrder, remontados)

# de la hisotoria reciente
circuitos_gp_recient <- full_join(carreras, circuitos, c("circuitId" = "circuitId")) %>% 
  select(circuitId, name.y, raceId, year) %>% 
  filter(year >= 1995)

ptos_remont_carrera_recient <- inner_join(puestos_remontados, circuitos_gp_recient)

puestos_remont_piloto_recient <- full_join(pilotos, ptos_remont_carrera_recient, c("driverId" = "driverId")) %>% 
  slice_max(remontados, n=10) %>% 
  select(driverId, driverRef, name.y, year,raceId, grid, positionOrder, remontados) %>% 
  slice(1:4,6:8,10) %>% 
  arrange(desc(remontados))


#--------------------------------
#mundiales por naionalidad y piloto
campeones <- full_join(pilotos, resultados, c("driverId" = "driverId")) %>% 
  full_join(., carreras, c("raceId" = "raceId")) %>% 
  select(driverId, driverRef, nationality, constructorId, points, year, round) %>% 
  full_join(., escuderias, c("constructorId" = "constructorId")) %>% 
  select(driverId, driverRef, nationality.x, constructorId, points, year, name, round) %>%  
  group_by(year, driverRef) %>%  
  mutate(puntos_totales = cumsum(points)) %>% 
  ungroup() %>% 
  group_by(year) %>% 
  slice_max(puntos_totales, n=1) %>% 
  ungroup() %>% group_by(driverRef) %>% 
  mutate(total_campeonatos = sum(NN = n())) %>% 
  distinct(driverRef, nationality.x, total_campeonatos) %>% 
  arrange(nationality.x, total_campeonatos)

#----------------------------------
#temporada 2021 tabla

pilotos_2021 <- full_join(carreras, resultados, c("raceId" = "raceId") ) %>% 
  full_join(.,pilotos, c("driverId"="driverId")) %>% 
  filter(year=="2021") %>% 
  select(forename,surname, year) %>% 
  distinct(forename,surname) %>% 
  na.omit() %>% 
  arrange(surname) %>% 
  str_replace_all(., "é", "é") %>% 
  str_replace_all(., "ä", "ä") %>% 
  str_replace_all(., "ö", "ö")

nombres_normales <- c("Alonso", "Bottas", "Gasly", "Giovinazzi", "Hamilton", "Latifi", "Leclerc", "Mazepin", "Norris", "Ocon", "Pérez", "Räikkönen", "Ricciardo", "Russell", "Sainz", "Schumacher", "Stroll", "Tsunoda", "Verstappen", "Vettel")

pilotos_2021 <-  full_join(carreras, resultados, c("raceId" = "raceId") ) %>% 
  full_join(.,pilotos, c("driverId"="driverId")) %>% 
  filter(year=="2021") %>% 
  select(forename,surname, year) %>% 
  distinct(forename,surname) %>% 
  na.omit() %>% 
  arrange(surname) %>% 
  add_column(nombres_normales) 

#--------------------------
#temporada 2021 templos

carreras_21 <- full_join(carreras,circuitos, c("circuitId" = "circuitId")) %>%
  filter(year=="2021") %>%
  select(round, name.x, name.y, date, location,country, lat, lng, alt) %>%
  arrange(round) %>% 
  mutate(round2 = round) 

carreras_21_v2 <- carreras_21[, c(1, 4, 10, 2, 3, 5, 6, 7, 8, 9)]
carreras_21_v2 <- carreras_21_v2%>%  unite(. ,variables, c(1, 5, 7), sep = "; ")


#----------------------------------
#el nano contra todos


alovsall <- full_join(pilotos, resultados, c ("driverId" = "driverId")) %>%  
  select(driverRef, resultId, raceId, constructorId, position, points) %>% 
  full_join(., escuderias, c ("constructorId" = "constructorId")) %>% 
  select(driverRef, resultId, raceId, constructorId, position, position, points, name) %>% 
  full_join(., carreras, c ("raceId" = "raceId")) %>% 
  select(driverRef, resultId, raceId, constructorId, position, position, points, name.x, year, round)

#alo_vs_marques <- alovsall %>% filter(year == 2001, driverRef %in% c("alonso", "marques"), round <= 14)

alo_vs_trulli <- alovsall %>% filter(year %in% c(2003, 2004), driverRef %in% c("alonso", "trulli")) %>% slice(1:15, 17:67) %>% group_by(driverRef, year) %>% mutate(puntos_acumulados = cumsum(points)) %>% ungroup()

alo_vs_fisichella <- alovsall %>% filter(year %in% c(2005, 2006), driverRef %in% c("alonso", "fisichella"))  %>% group_by(driverRef, year) %>% mutate(puntos_acumulados = cumsum(points)) %>% ungroup()

alo_vs_hamilton <- alovsall %>% filter(year %in% c(2007) ,driverRef %in% c("alonso", "hamilton"))  %>% group_by(driverRef, year) %>% mutate(puntos_acumulados = cumsum(points)) %>% ungroup()

alo_vs_piquet <- alovsall %>% filter(year %in% c(2008, 2009), driverRef %in% c("alonso", "piquet_jr")) %>% slice(1:28, 36:63) %>% group_by(driverRef, year) %>% mutate(puntos_acumulados = cumsum(points)) %>% ungroup()

#alo_vs_grosjean <- alovsall %>% filter(year == 2009, driverRef %in% c("alonso", "grosjean"), round >= 11)

alo_vs_massa <- alovsall %>% filter(year %in% c(2010, 2011, 2013), driverRef %in% c("alonso", "massa")) %>% group_by(driverRef, year) %>% mutate(puntos_acumulados = cumsum(points)) %>% ungroup()

alo_vs_raikkonen <- alovsall %>% filter(year == 2014, driverRef %in% c("alonso", "raikkonen")) %>% group_by(driverRef, year) %>% mutate(puntos_acumulados = cumsum(points)) %>% ungroup()

alo_vs_button <- alovsall %>% filter(year %in% c(2015, 2016), driverRef %in% c("alonso", "button")) %>% group_by(driverRef, year) %>% mutate(puntos_acumulados = cumsum(points)) %>% ungroup()

alo_vs_vandoorne <- alovsall %>% filter(year %in% c(2017, 2018), driverRef %in% c("alonso", "vandoorne")) %>% slice(1:45, 47:81) %>% group_by(driverRef, year) %>% mutate(puntos_acumulados = cumsum(points))%>% ungroup() 

alo_vs_ocon <- alovsall %>% filter(year == 2021, driverRef %in% c("alonso", "ocon")) %>% group_by(driverRef, year) %>% mutate(puntos_acumulados = cumsum(points)) %>% ungroup()

ALO_VS_ALL <- full_join(alo_vs_trulli, alo_vs_fisichella, c("driverRef"= "driverRef", "resultId" = "resultId", "raceId" = "raceId", "constructorId" = "constructorId", "position" = "position", "points" = "points", "name.x" = "name.x", "year" = "year", "round" = "round" , "puntos_acumulados" = "puntos_acumulados")) %>% 
  full_join(., alo_vs_hamilton, c("driverRef"= "driverRef", "resultId" = "resultId", "raceId" = "raceId", "constructorId" = "constructorId", "position" = "position", "points" = "points", "name.x" = "name.x", "year" = "year", "round" = "round", "puntos_acumulados" = "puntos_acumulados")) %>% 
  full_join(., alo_vs_piquet, c("driverRef"= "driverRef", "resultId" = "resultId", "raceId" = "raceId", "constructorId" = "constructorId", "position" = "position", "points" = "points", "name.x" = "name.x", "year" = "year", "round" = "round", "puntos_acumulados" = "puntos_acumulados")) %>% 
  full_join(., alo_vs_massa, c("driverRef"= "driverRef", "resultId" = "resultId", "raceId" = "raceId", "constructorId" = "constructorId", "position" = "position", "points" = "points", "name.x" = "name.x", "year" = "year", "round" = "round", "puntos_acumulados" = "puntos_acumulados"))  %>% 
  full_join(., alo_vs_raikkonen, c("driverRef"= "driverRef", "resultId" = "resultId", "raceId" = "raceId", "constructorId" = "constructorId", "position" = "position", "points" = "points", "name.x" = "name.x", "year" = "year", "round" = "round", "puntos_acumulados" = "puntos_acumulados")) %>% 
  full_join(., alo_vs_button, c("driverRef"= "driverRef", "resultId" = "resultId", "raceId" = "raceId", "constructorId" = "constructorId", "position" = "position", "points" = "points", "name.x" = "name.x", "year" = "year", "round" = "round", "puntos_acumulados" = "puntos_acumulados")) %>% 
  full_join(., alo_vs_vandoorne, c("driverRef"= "driverRef", "resultId" = "resultId", "raceId" = "raceId", "constructorId" = "constructorId", "position" = "position", "points" = "points", "name.x" = "name.x", "year" = "year", "round" = "round", "puntos_acumulados" = "puntos_acumulados")) %>% 
  full_join(., alo_vs_ocon, c("driverRef"= "driverRef", "resultId" = "resultId", "raceId" = "raceId", "constructorId" = "constructorId", "position" = "position", "points" = "points", "name.x" = "name.x", "year" = "year", "round" = "round", "puntos_acumulados" = "puntos_acumulados"))


#------------------------------
#el nano contra hamilton
fotos_ALO_vs_HAM <- c("./imagenes/pilotos/alonso.png", "./imagenes/pilotos/hamilton.png")
fotos_esp_ing <- c("./imagenes/paises/espanya.png", "./imagenes/paises/uk.png")
n_carreras_alo_ham <- n_carreras_nom %>% filter(driverRef %in% c("alonso", "hamilton"))

n_victorias_alo_ham <- victorias_con_nombre %>% filter(driverRef %in% c("alonso", "hamilton"))

alo_vs_ham <- full_join(n_carreras_alo_ham, n_victorias_alo_ham, c("driverRef"= "driverRef")) %>% select( driverRef, numero_carreras, n_victorias) %>% add_column(fotos_esp_ing, fotos_ALO_vs_HAM) 

3. The plan

3.1 Un paseo por la historia

El nacimiento de la Fórmula 1 se remonta a 1950, donde la FIA, Federación Internacional del Automóvil, decidió unir varios grandes premios de diferentes países, para crear el campeonato mundial de pilotos. El primer gran premio se celebró en el circuito de Silverstone, el 13 de mayo de 1950. Desde entonces, La Fórmula 1 ha ido evolucionando, tanto a nivel de coches, circuitos, o logos, para acabar siendo el espectáculo que es en la actualidad.

Coches

El automóvil puede ser el elemento que mayores cambios ha experimetnado con el paso del tiempo. En los años 50, las escuderias más destacables eran los propios fabricantes de vehículos, por ejemplo Maserati o Alfa Romeo. Los coches en esta década se caracterizaban por tener un motor frontal, a diferencia de lo que pasaría en años posteriores.

A partir de la década de los 60, se comenzaron a utilizar vehículos con motor central, suponiendo una importante mejora en el desempeño de los coches. Además, se dio peso a otros aspectos, como la composición del chasis, siendo la escudería lotus pionera en introducir los chasis monocasco de aluminio.

En los 70, la aerodinámica pasó a tener un papel fundamental, introduciendose el efecto suelo, q permitía rodar a mayor velocidad en las curvas. Entre 1980 y 1990 destacan las ayudas electrónicas, como por ejemplo la suspensión activa, el cambio de marchas semi-automático, o el control de tracción.

Desde entonces, hasta la actualidad, los cammbios en los coches no han sido tan relevantes, produciendose un equilibrio en las mejoras de las distintas partes del vehículo: aerodinámica, chasis y motor.


coche1950 <- image_read("./imagenes/coches/1950.jpg") %>% image_scale(., "500") %>%  image_annotate(., "1950", size = 40, gravity = "southwest", color = "white")
coche1960 <- image_read("./imagenes/coches/1960.jpg") %>% image_scale(., "500")%>%  image_annotate(., "1960", size = 40, gravity = "southwest", color = "white")
coche1970 <- image_read("./imagenes/coches/1970.jpg") %>% image_scale(., "500")%>%  image_annotate(., "1970", size = 40, gravity = "southwest", color = "white")
coche1980 <- image_read("./imagenes/coches/1980.jpg") %>% image_scale(., "500")%>%  image_annotate(., "1980", size = 40, gravity = "southwest", color = "white")
coche1990 <- image_read("./imagenes/coches/1990.jpg") %>% image_scale(., "500")%>%  image_annotate(., "1990", size = 40, gravity = "southwest", color = "white")
coche2005 <- image_read("./imagenes/coches/2005.jpg") %>% image_scale(., "500")%>%  image_annotate(., "2005", size = 40, gravity = "southwest", color = "white")
coche2020 <- image_read("./imagenes/coches/2020.jpg") %>% image_scale(., "500")%>%  image_annotate(., "2020", size = 40, gravity = "southwest", color = "white")
coches <- c(coche1950, coche1960, coche1970, coche1980, coche1990, coche2005, coche2020)

image_animate(image_scale(coches), fps = 0.5)

Logos

Logo de 1985 a 1986

Aunque no tan espectacular, también se ha producido ua evolución de la estética del logo, pasando de una imagen más cargada, en la que aparece hasta el símbolo de la FIA, al logo actual, compuesto por la F y el 1.

Logo de 1950 a 1986

Logo de 1987 a 1993

Logo de 1987 a 1993

Logo de 1994 a 2017

Logo de 1994 a 2017

Logo Actual

LOGO desde 2018 hasta la actualidad

Capítulo oscuro del deporte

Hay que ser conscientes que, de igual manera que la Formula 1 es espectacular, sus pilotos se exponen a un gran riesgo. Prueba de ello es, el gráfico mostrado a continuación, en el cual se refleja todas las muertes de pilotos producidas en la F1. El total es de 42, siendo la peor decada los años 50, produciendose 15 fallecimientos. En dicho periodo, destaca sobre los demás circuito las 500 millas de Indianápolis, la cual estaba durante los primeros años de la F1 dentro de los circuitos del campeonato. Por otro lado, cabe destacar las muertes de Roland Ratzenberger y Ayrton Senna, en el gran premio de San Marino de 1994. Supuso un punto de inflexión en la seguridad de las carreras, debido a que desde 1960, no se habían producido dos muertes en un mismo fin de semana, sumado a que Ayrton Senna era una de las estrellas de la F1 en ese momento. Desde esa fecha no se volvieron a producir muertes de pilotos hasta el gran premio de Japón de 2014, falleciendo Jules Bianchi, siendo la última muerte.

Sin embargo, la tendencia ha sido claramente negativa, debido a las diferentes medidas de seguridad que se han ido incorporando.Algunas de las mejoras más destacadas han sido, las proteciones y grava en los circuitos, los monos ignífugos o la reglamentación en el diseño del casco.La última introducción ha sido el halo, centrado en evitar golpes o aplastamientos de la cabeza del piloto. A pesar de algunas críticas, su papel ya ha sido fundamental, por ejemplo para evitar mayores daños en el accidente que sufrió el piloto Romain Grosjean en el gran premio de Bahrein en 2020.

gg_muertes <- ggplot(muertesf1_final, aes(x = fecha_muerte, y = muertesxanyo )) +  geom_bar(stat = "identity", fill = "white", colour = "white") + geom_smooth(colour = "cyan", se = FALSE) + labs(x = "Año" , y = "Número de muertes")  + theme(axis.line = element_line(colour = "white"),
    axis.ticks = element_line(colour = "white"),
    panel.grid.major = element_line(colour = "gray13"),
    panel.grid.minor = element_line(colour = "gray13"),
    axis.title = element_text(colour = "white"),
    axis.text = element_text(colour = "white"),
    plot.title = element_text(colour = "white"),
    panel.background = element_rect(fill = "gray13",
        colour = "white"), plot.background = element_rect(fill = "gray13")) +labs(colour = "white") + theme(panel.grid.major = element_line(colour = "gray38",
    linetype = "dotted"), panel.grid.minor = element_line(colour = NA),
    plot.title = element_text(size = 25,
        hjust = 0.5)) +labs(title = "Accidentes mortales por año") + geom_text(data = data.frame(x = 2004.10522642875, y = 0.237450516942241, 
    label = "Tendencia negativa"), mapping = aes(x = x, y = y, 
    label = label), colour = "cyan", inherit.aes = FALSE, size = 3)

ggplotly(gg_muertes)

3.2 Lo más destacado

Como se indica al inicio del trabajo, la F1 es un deporte en el que los datos tienen una gran importancia. Pero dicha información no solo es útil para los pilotos/escuderias, sino que también permite realizar otro tipo de análisis, por ejemplo, desde el punto de la F1 como negocio, estudiando las audiencias, el dinero otenido por publicidad, o los asistentes a cada gran premio celebrado. Por otro lado, puede servir para los aficionados a la hora de comparar sus pilotos favoritos, o que escudería es la mejor.

Audencias

El número de personas que siguen la Formula 1 en nuestro país ha dependido en gran medida de la figura de Fernando Alonso. Prueba de ello es el gráfico mostrado abajo, el cual refleja las audiencias de F1 en España entre 2004 y 2020.

Cuanto más crecían las victorias de Alonso, ganando el mundial de pilotos en 2005 y 2006, más personas seguían la formula 1, llegando a su pico en 2007, donde se produjo una temporada llena de polémicas entre Alonso, Hamilton y el equipo McLaren, alcanzando cifras de 4,5 millones de espectadores. Se produjo un pequeño bajón los dos años posteriores, ya que la vuelta de Alonso a renault no fue muy existosa. Las audiencias se volvieron a disparan con la llegada del asturiano a Ferrrari, pero despues de dos subcampeonatos, los espectadores fueron decayendo, y más con las desastrosas temporadas que tuvo en McLaren entre 2015 y 2018. Si a esto le sumamos que a partir de 2016 la F1 solo se podía seguir a través de plataformas de pago en España, nos econtramos con cifras bajisimas en la última etapa.

audiencias <- rio::import(file = "./datos/audienciasF1.csv")


gg_audiencias <- ggplot(audiencias, aes(x=year, y= numero_espectadores)) +
  geom_area() +
  geom_point( size=1.5, color="cyan", fill=alpha("cyan", 8), shape=21, stroke=2) +  
  geom_line(color="#69b3a2", size=1) +
  scale_x_continuous(
    breaks = seq(2004, 2020, 1),
    limits = c(2003, 2021)) + labs(x = "Año", y = "Numero de espectadores" )  + theme(panel.background = element_rect(fill = "gray13"),
    plot.background = element_rect(fill = "gray13")) + theme(axis.line = element_line(colour = "white"),
    panel.grid.major = element_line(colour = "gray20"),
    panel.grid.minor = element_line(colour = "gray20"),
    axis.text = element_text(colour = "white"),
    legend.position = "none") + theme(axis.title = element_text(colour = "white"),
    plot.title = element_text(colour = "white",
        hjust = 0.5)) +labs(title = "Evolución de la audiencia",
    colour = "white") + theme(axis.text.x = element_text(size = 4))


ggplotly(gg_audiencias)

Presupuestos

El presupuesto de las escuderias siempre ha sido un tema muy polémico en el mundo de la F1. Cuanto mayor sea el presupuesto de una escudería, mayores posibilidades tendrá de ganar el mundial, por lo que puede llegar a cuestionarse si, el piloto ganador es aquel con mayor habilidad, o aquel que posee el monoplaza con mayor inversión detrás.

El gráfico dispuesto a continuación muestra que ,desde 2015 a 2020, los años en los que ha ganado Mercedes el mundial, la escudería era con la que más presupuesto contaba, excepto en 2015, donde era la segunda con muy poca diferencia con Red Bull. Sin embargo, tal y como muestra la gráfica, se espera un nuevo reglamento para 2022, que incluirá la implementación de un techo presupuestario de 140 millones de euros, y que se reducirá a 2023 a 135 millones, para todas las escuderias.


presupuestos <- read_excel("datos/presupuestos.xlsx")

gg_presup <- ggplot(presupuestos, aes(year, Presupuesto, color = Escuderia)) + 
  geom_point() + geom_line() + 
  labs(x = "Año", y = "Presupuesto en €" ) +
    scale_x_continuous(
    breaks = seq(2015, 2023, 1),
    limits = c(2014, 2024)) + 
  scale_y_continuous( breaks = seq(0, 700000000, 100000000),
    limits = c(0, 600000000))  + theme(axis.ticks = element_line(colour = "white"),
    panel.grid.major = element_line(colour = "white",
        linetype = "blank"), panel.grid.minor = element_line(colour = "white",
        linetype = "blank"), axis.title = element_text(size = 14,
        face = "bold", colour = "cyan", vjust = 0.75),
    axis.text = element_text(colour = "white"),
    plot.title = element_text(size = 16,
        face = "bold", colour = "cyan", hjust = 0.5,
        vjust = 0.75), legend.text = element_text(face = "bold",
        colour = "cyan"), legend.title = element_text(size = 13,
        face = "bold", colour = "cyan"),
    panel.background = element_rect(fill = "gray13",
        colour = "white"), plot.background = element_rect(fill = "gray13"),
    legend.key = element_rect(fill = "gray13"),
    legend.background = element_rect(fill = "gray13")) +labs(title = "PRESUPUESTO DE CADA EQUIPO POR TEMPORADA") + theme(panel.grid.major = element_line(colour = NA),
    panel.grid.minor = element_line(colour = NA),
    axis.title = element_text(size = 11),
    plot.title = element_text(size = 14),
    legend.text = element_text(size = 9),
    legend.title = element_text(size = 11),
    panel.background = element_rect(fill = "gray13",
        colour = NA), plot.background = element_rect(fill = "gray13",
        colour = NA)) + theme(legend.key = element_rect(fill = "gray13"),
    legend.background = element_rect(fill = "gray13")) + theme(axis.line = element_line(colour = "gray20",
    linetype = "solid"), panel.grid.major = element_line(colour = "gray15",
    linetype = "solid"))
 
ggplotly(gg_presup) #para que sea interactivo

Nacionalidades

En los comienzos de la Formula 1, la gran mayoría de los pilotos eran del continente europeo, destanco Gran Bretaña. Este hecho se debía en parte a que la mayoría de los circuitos se encontraban en Europa. Sin embargo, con el paso de las años, el deporte se volvió cada vez más internacional. Fuera de Europa destaca Estados Unidos, siendo el segundo país con más pilotos en la historia, en sudamérica Brasil y Argentina, en Asia Japon, y en Oceanía Australia. En África, solo hay dos países con representación, Sudáfrica con 23 y Zimbabue con 4. En España el total de representantes ha sido 15. A pesar de su apartura, sigue existiendo un claro predominio europeo, por ejemplo en la temporada actual, casi 3/4 de la parrilla son pilotos con nacionalidad europea.

Mapa


ggplotly(gg_pilotos_por_paises)

Tabla


set_flextable_defaults(
  font.size = 15,
  font.color = "white",
  table.layout = "fixed", 
  background.color = "gray13")

flex_piloto <- flextable(nacionalidad)

small_border = fp_border(color="gray50", width = 2)

flex_piloto1 <- border_outer(flex_piloto, part="all", border = small_border )


theme_vader(flex_piloto1)

Pilotos con más victorias

Ganar una carrera en F1 representa haber sido el mejor piloto de la parrilla durante un gran premio, y tiene un gran valor, debido a la elevada competitividad que existe en este deporte. Por tanto, a pesar de no ser la única, es una buena variable para medir las capacidades de un piloto.
El gráfico siguiente muestra dicha variable, las victorias, pero de los 16 pilotos que más han conseguido a lo largo de su historia. Destacan sobre el resto Lewis Hamilton, con 98 victorias, y Michael Schumacher, con 91. Fernando Alosno se encuentra el sexto con 32. Cabe destacar que, varios de estos pilotos siguen en activo, Alonso, Vettel y Hamilton, por lo que podrán seguir aumentando su palmarés.


ggplot(victorias2, aes(x = reorder(driverRef,suma_vic), suma_vic)) + 
  geom_line(size=5, colour = "cyan") +
  coord_flip() +
  theme(plot.subtitle = element_text(hjust = 0.5),
    plot.caption = element_text(size = 15,
        colour = "white", hjust = 0), axis.line = element_line(colour = "gray20",
        linetype = "solid"), panel.grid.major = element_line(linetype = "blank"),
    panel.grid.minor = element_line(linetype = "blank"),
    axis.title = element_text(colour = "cyan"),
    axis.text = element_text(colour = "cyan"),
    axis.text.x = element_text(colour = "white"),
    axis.text.y = element_text(colour = "white"),
    plot.title = element_text(size = 17,
        colour = "white", hjust = 0.5), panel.background = element_rect(fill = "gray13",
        colour = "gray13", linetype = "solid"),
    plot.background = element_rect(fill = "gray13",
        colour = "gray13", linetype = "solid")) +labs(title = 'Pilotos con más victorias' ,x = "Pilotos",
    y = "Nº victorias") + theme(plot.subtitle = element_text(colour = "gray50"),
    plot.title = element_text(face = "bold",
        colour = "cyan")) +labs(title = "PILOTOS CON MÁS VICTORIAS",
    subtitle = ) #+ transition_reveal(date)

Remando a contracorriente

Los adelantamientos son un elemnto básico en las carreras, y más en la F1. La lucha por una posición puede generar momentos de tensión, toques o accidentes en algunas ocasiones, o en otras ocasiones pueden ser simplemente limpios. En ambos casos, añaden dinamismo a las carreras, consiguiendo mantener la atención del espectador. Por eso, uno de los momentos más importantes y más vistos de una carrera es la salida, debido a que todos los pilotos pretenden realizar la trazada más rápida, juntandose en pocos metros, e incremmentando considerablemente los riesgos de una colisión.

El siguiente gráfico muestra las mayores remontadas de la historia moderna de la F1, es decir, carreras donde los pilotos nombrados consiguieron realizar pilotajes brillantes, debido a un elevado número de adelantamientos. En primer lugar se encuentra la carrera que realizó Vettel en 2012 en el circuito de Yas Marina, consiguiendo remontar 21 puestos. Pero sin duda, la carrera más destacada es la llevado a cabo en 2010 por Fernando Alonso, que consiguió remontar 18 puestos en el más que complicadísimo circuito urbano de Mónaco.

trulli <- readPNG("./imagenes/pilotos/trulli.png")
kovalainen <- readPNG("./imagenes/pilotos/kovalainen.png")
vettel <- readPNG("./imagenes/pilotos/vettel.png")
raikkonen <- readPNG("./imagenes/pilotos/raikkonen.png")
schumacher <- readPNG("./imagenes/pilotos/schumacher.png")
hamilton <- readPNG("./imagenes/pilotos/hamilton.png")
montoya <- readPNG("./imagenes/pilotos/montoya.png")
alonso <- readPNG("./imagenes/pilotos/alonso.png")

trulli_grob <- rasterGrob(trulli, interpolate=TRUE)
kovalainen_grob <- rasterGrob(kovalainen, interpolate=TRUE)
vettel_grob <- rasterGrob(vettel, interpolate=TRUE)
raikkonen_grob <- rasterGrob(raikkonen, interpolate=TRUE)
schumacher_grob <- rasterGrob(schumacher, interpolate=TRUE)
hamilton_grob <- rasterGrob(hamilton, interpolate=TRUE)
montoya_grob <- rasterGrob(montoya, interpolate=TRUE)
alonso_grob <- rasterGrob(alonso, interpolate=TRUE)


ggremontados <- ggplot(puestos_remont_piloto_recient, aes(x = reorder(driverRef, remontados), remontados))  + geom_bar(stat = "identity") + coord_flip() + labs(x = "Pilotos", y = "Nº de puestos remontados" ) + annotation_custom(alonso_grob, xmin= -15, xmax=17, ymin= 18, ymax=20) +
  annotation_custom(kovalainen_grob, xmin= -20, xmax=24, ymin= 18.65, ymax=20) +
  annotation_custom(montoya_grob, xmin= -26.7, xmax=33, ymin= 18, ymax=21.2) +
  annotation_custom(trulli_grob, xmin= -32, xmax=40., ymin= 18.3, ymax=19.55) +
  annotation_custom(hamilton_grob, xmin= -32, xmax=42.2, ymin= 19, ymax=21.8) +
  annotation_custom(schumacher_grob, xmin= -32, xmax=44.1, ymin= 19.2, ymax=20.5) +
  annotation_custom(raikkonen_grob, xmin= -32, xmax=46.1, ymin= 19, ymax=21) +
  annotation_custom(vettel_grob, xmin= -32, xmax=48.1, ymin= 19, ymax=21.2) +
    theme(axis.line = element_line(colour = "white"),
    axis.ticks = element_line(colour = NA),
    panel.grid.major = element_line(colour = "cyan",
        linetype = "blank"), panel.grid.minor = element_line(colour = "gray20"),
    axis.title = element_text(face = "bold",
        colour = "gray50"), axis.text = element_text(size = 11,
        colour = "cyan"), axis.text.x = element_text(colour = "cyan"),
    axis.text.y = element_text(colour = "cyan"),
    plot.title = element_text(size = 15,
        face = "bold", colour = "cyan", hjust = 0.45,
        vjust = 0.75), panel.background = element_rect(fill = "gray13",
        linetype = "solid"), plot.background = element_rect(fill = "gray13",
        colour = "cyan", linetype = "solid")) +labs(title = "MAYORES REMONTADAS EN LA HISTORIA")
  

ggremontados

Mundiales por escuderias y pilotos

El mayor premio para un piloto y una escudería es alzarse con el título de campeón del mundial al final de una temporada, mostrando al equipo y piloto con mayor regularidad, y el que en la gran parte de las ocasiones sea el mejor vehículo de ese año.

La escudería más galardonada es McLaren con 9 campeonatos mundiales, conseguidos su gran mayoría en la época de los 80. Le sigue Ferrari, con 8 títulos, siendo considerada por muchos, la escudería más emblemática. Dentro de ambas escderias, aparecen pilots que destapan sobre el resto. En el caso de McLaren, tanto Prost como Senna son los pilotos más relevantes, y en el caso de Ferrari, Michael Schumacher.

En valores relativos

#datos de escuderias pa quien quiera hacer algo
#escuderias <- rio::import(file = "./datos/constructors.csv")
#escuderias2 <- rio::import(file = "./datos/constructor_standings.csv")
#result_escuderias <- rio::import(file = "./datos/constructor_results.csv")

#pilotos <- rio::import(file = "./datos/drivers.csv")
#resultados <- rio::import(file = "./datos/results.csv")
#carreras <- rio::import(file = "./datos/races.csv")
#escuderiasesp <- escuderias %>% filter(nationality == "Spanish") #escuderias españolas

#campeones_esc <- full_join(pilotos, resultados, c("driverId" = "driverId")) %>% full_join(., carreras, c("raceId" = "raceId")) %>% select(driverId, driverRef, nationality, constructorId, points, year, round) %>% full_join(., escuderias, c("constructorId" = "constructorId")) %>% select(driverId, driverRef, nationality.x, constructorId, points, year, name, round) %>%  group_by(year, driverRef) %>%  mutate(puntos_totales = cumsum(points)) %>% ungroup() %>% group_by(year) %>% slice_max(puntos_totales, n=1) %>% select(name, driverRef) %>% group_by(name, driverRef) %>% mutate(total_camp = sum( NN = n())) %>% arrange(name) 




#library(treemap)
#library(d3treeR)


# basic treemap
#gg_esc_campeones <- treemap(campeones_esc,
            #index=c("name","driverRef"),
            #vSize="total_camp",
            #type="index",
            #vColor = "name",
            #fontsize.labels=c(25,17),
            #bg.labels=c("transparent"),
            #palette = "Set2",
            #align.labels=list(
              #c("center", "center"), 
              #c("center", "bottom")),
            #title = "Escuderías con más campeones",
            #title.legend = "Escuderías")   

inter_camp <- d3tree2(gg_esc_campeones ,  rootname = "Escuderías y Campeones")
inter_camp

En valores absolutos

campeones_esc <- full_join(pilotos, resultados, c("driverId" = "driverId")) %>% full_join(., carreras, c("raceId" = "raceId")) %>% select(driverId, driverRef, nationality, constructorId, points, year, round) %>% full_join(., escuderias, c("constructorId" = "constructorId")) %>% select(driverId, driverRef, nationality.x, constructorId, points, year, name, round) %>%  group_by(year, driverRef) %>%  mutate(puntos_totales = cumsum(points)) %>% ungroup() %>% group_by(year) %>% slice_max(puntos_totales, n=1) %>% ungroup() %>% count(name) %>% arrange(desc(n))

campeones_esc$n=as.factor(campeones_esc$n)

gg_campeones_es <- ggplot(campeones_esc, aes(x=name, y=n)) +
  geom_bar(stat="identity", width=2, color="white") + 
  theme(axis.line = element_line(colour = "gray13"),
    axis.ticks = element_line(colour = "gray13"),
    panel.grid.major = element_line(colour = "gray13"),
    panel.grid.minor = element_line(colour = "gray13"),
    axis.title = element_text(family = "Bookman",
        size = 8, face = "bold"), axis.text = element_text(face = "bold",
        colour = "cyan"), axis.text.x = element_text(colour = "gray13"),
    axis.text.y = element_text(colour = "gray13"),
    plot.title = element_text(family = "Bookman",
        size = 14, face = "bold", colour = "cyan", hjust=0.5),
    legend.text = element_text(size = 9,
        face = "bold", colour = "cyan"),
    legend.title = element_text(size = 8,
        face = "bold", colour = "gray13"),
    panel.background = element_rect(fill = "gray13",
        colour = "gray13", linetype = "solid"),
    plot.background = element_rect(fill = "gray13",
        colour = "gray13", linetype = "solid"),
    legend.key = element_rect(fill = "cyan"),
    legend.background = element_rect(fill = "gray13")) +labs(title = "CAMPEONATOS POR ESCUDERIA",
    x = NULL, y = NULL)


ggplotly(gg_campeones_es)

Mundiales por pilotos y nacionalidad

Si analizamos los campeonatos mundiales por pilotos, hay 3 nombres que se alzan sobre el resto. Michael Schumacher, con 9 títulos mundiales, Prost con 8 y Hamilton con 7. A nivel nacional, Gran Bretaña se alza claramente como el país con más titulos mundiales, muy por encima del resto de paises.



id <- rownames(campeones)
campeones <- cbind(id=id, campeones)
campeones[, c(1)] <- sapply(campeones[, c(1)], as.numeric)

label_campeones <- campeones
number_of_bar <- nrow(label_campeones)

angle <- 90 - 360 * (label_campeones$id-0.5) /number_of_bar    
label_campeones$hjust <- ifelse( angle < -90, 1, 0)
label_campeones$angle <- ifelse(angle < -90, angle+180, angle)

base_campeones <- campeones %>% 
  group_by(nationality.x) %>% 
  summarise(start=min(id), end=max(id)) %>% 
  rowwise() %>% 
  mutate(title=mean(c(start, end)))

grid_campeones <- base_campeones
grid_campeones$end <- grid_campeones$end[ c( nrow(grid_campeones), 1:nrow(grid_campeones)-1)] + 1
grid_campeones$start <- grid_campeones$start - 1
grid_campeones <- grid_campeones[-1,]

gg_circ_victorias <- ggplot(campeones, aes(x=as.factor(year), y=total_campeonatos, fill=nationality.x, color = nationality.x)) + geom_bar(aes(x=as.factor(id), y=total_campeonatos, fill=nationality.x), stat="identity", alpha=0.5) +
  
  geom_segment(data=grid_campeones, aes(x = 0, y = 8, xend = 32, yend = 8), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 0, y = 6, xend = 32, yend = 6), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 0, y = 4, xend = 32, yend = 4), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 0, y = 2, xend = 32, yend = 2), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  
  annotate("text", x = rep(max(campeones$id),4), y = c(2, 4, 6, 8), label = c("2", "4", "6", "8") , color="white", size=3 , angle=0, fontface="bold", hjust=1) +
  
   geom_bar(aes(x=as.factor(id), y=total_campeonatos, fill=nationality.x), stat="identity", alpha=0.5) +
  ylim(-10,21) +
  theme_minimal() +
  theme(
    legend.position = "none",
    axis.text = element_blank(),
    axis.title = element_blank(),
    panel.grid = element_blank(),
    plot.margin = unit(rep(-1,4), "cm") ) +
  coord_polar() + 
  geom_text(data=label_campeones, aes(x=id, y=10, label=driverRef, hjust=hjust), color="white", fontface="bold",alpha=0.6, size=3.5, angle= label_campeones$angle, inherit.aes = FALSE ) +

  geom_segment(data=grid_campeones, aes(x = 0.70, y = -1, xend = 2.45, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE )  +
  geom_segment(data=grid_campeones, aes(x = 2.6, y = -1, xend = 3.55, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 3.65, y = -1, xend = 5.45, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 5.55, y = -1, xend = 7.35, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 7.5, y = -1, xend = 10.50, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 10.7, y = -1, xend = 19.20, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 19.4, y = -1, xend = 20.3, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 20.45, y = -1, xend = 23.4, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) + 
  geom_segment(data=grid_campeones, aes(x = 23.65, y = -1, xend = 24.35, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) + 
  geom_segment(data=grid_campeones, aes(x = 24.60, y = -1, xend = 27, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 27.2, y = -1, xend = 29.5, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 29.7, y = -1, xend = 30.5, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) + 
  geom_segment(data=grid_campeones, aes(x = 30.7, y = -1, xend = 31.5, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 31.7, y = -1, xend = 32.5, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 32.7, y = -1, xend = 33.5, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) + theme(legend.text = element_text(colour = "white"),
    legend.title = element_text( colour = "white"), 
     legend.background = element_rect(fill = "gray13", colour = "gray13"),
    legend.key = element_rect(fill = "gray13"),
    legend.position = "right",
    panel.background = element_rect(fill = "gray13" , colour = "gray13"),
    plot.background = element_rect(fill = "gray13" , colour = "gray13"))+labs(colour = "Nacionalidad", fill = "Nacionalidad")
#gg_circ_victorias
#las siguientes lineas de codigo se utilizan para eliminar los bordes blancos
ggsave("./plots/gg_circ_victorias.png", width = 8, height = 5)

Campeones del mundo

3.3 Temporada 2021

Campeón del mundo

El pasado fin de semana el piloto holandés de 24 años Max Verstappen, se declaraba campeón de la temporada 2021 de Formula 1.Este, consiguió su gran triunfo, tras una dura lucha contra el piloto inglés Lewis Hamilton durante toda la temporada, llegando ambos a la última carrera del campeonato empatados a puntos, algo que solamente había sucedido una vez en la historia.

Verstappen

Verstappen - Nuevo Campeón 2021

Final de infarto

El finde semana, comenzaba bien para el piloto holandés, ya que el sábado se alzó con la pole, saliendo así en el primer puesto de la carrera. Pero todo se comenzó a torcer cuando Hamilton le adelanto en la salida, y Verstappen no podía alcanzarlo. El piloto inglés reinó la carrera durante 53 vueltas de 56 que tenía el gran Premio de Yas Marina. Todo parecía apuntar a que Hamilton iba a conseguir su octavo campeonato del mundo, pero en esta vuelta 53, el piloto canadiense Latifi sufrió un accidente que provocó la salida del safety car, y por tanto todos los coches se iban a volver a juntar unos detrás de otros reduciendo sus distancias, aprovechando el equipo Red Bull para en una gran jugada de estrategia entrar a boxes para montar el neumático blando, y tras la salida del safety car, el joven piloto holandés consiguió adelantar en la última vuelta del campeonato a Lewis Hamilton, y así alzarse con el título de una de las temporadas más emocionantes de la F1.


salida <- image_read("./imagenes/CAMPEON/hamilton_adel.jpg") %>% image_scale(., "500")%>%  image_annotate(., "Hamilton se pone por delante", size = 20, gravity = "northwest", color = "cyan", boxcolor = "gray13")
latifi <- image_read("./imagenes/CAMPEON/latifi.jpg") %>% image_scale(., "500")%>%  image_annotate(., "Accidente de Latifi", size = 40, gravity = "northwest", color = "cyan", boxcolor = "gray13")
safety <- image_read("./imagenes/CAMPEON/safety.jpg") %>% image_scale(., "500")%>%  image_annotate(., "Sale el safety car", size = 40, gravity = "northwest", color = "cyan", boxcolor = "gray13")
rueda_a_rueda <- image_read("./imagenes/CAMPEON/ruedaarueda.jpeg") %>% image_scale(., "500")%>%  image_annotate(., "Igualdad máxima", size = 30, gravity = "northwest", color = "cyan", boxcolor = "gray13")
meta <- image_read("./imagenes/CAMPEON/verstappen_gana.jpg") %>% image_scale(., "500")%>%  image_annotate(., "Verstappen se hace con la victoria", size = 20, gravity = "northwest", color = "cyan", boxcolor = "gray13")
trofeo <- image_read("./imagenes/CAMPEON/campeon_trofeo.jpg") %>% image_scale(., "500")%>%  image_annotate(., "Nuevo campeón del mundo", size = 30, gravity = "northwest", color = "cyan", boxcolor = "gray13")
last_race <- c(salida, latifi, safety, rueda_a_rueda, meta, trofeo)

image_animate(image_scale(last_race), fps = 0.5)

Verstappen vs Hamilton

En la siguiente tabla puede observarse la igualdad que ha existio entre los dos pilotos a lo largo del campeonato del mundo, llegando incluso empatados a puntos a la última carrera.

vers_vs_ham <- data.frame(
  "nombre" = c("Max Verstappen", "Lewis Hamilton"),
  "piloto" = c("./imagenes/pilotos/verstappen.jpg","./imagenes/pilotos/hamilton.png"),
  "pais" = c("./imagenes/paises/holanda.png", "./imagenes/paises/uk.png"),
  "escuderia" = c("./imagenes/escuderias/redbull.png", "./imagenes/escuderias/mercedes.png"),
  "puntos" = c(395.5, 387.5),
  "victorias" = c(10, 8),
  "podiums" = c(18, 17),
  "poles" = c(10, 5),
  "vueltas_rapidas" = c(6, 6))
  

 
tabla_ver_ham <- vers_vs_ham %>% gt() %>% 
  text_transform( locations = cells_body(columns = c(piloto)), fn = function(x) {gt::local_image(x, height = 80)}) %>% 
  text_transform( locations = cells_body(columns = c(pais)), fn = function(x) {gt::local_image(x, height = 60)}) %>%  
  text_transform( locations = cells_body(columns = c(escuderia)), fn = function(x) {gt::local_image(x, height = 80)}) %>% 
  tab_header(title = md("**Verstappen vs Hamilton**"), subtitle = md("2021")) %>%   cols_label(
    nombre = html(""),
    piloto = html(""),
    pais = html(""),
    escuderia = html("Escudería"),
    puntos = html("Puntos"),
    victorias = html("Victorias"),
    podiums = html("Podiums"),
    poles = html("Poles"),
    vueltas_rapidas = html("Vueltas rápidas")) %>%  
  tab_options(table.background.color = "gray13",   table.font.color.light = "cyan") %>% 
  cols_align(align = "center",
  columns = everything())


tabla_ver_ham
Verstappen vs Hamilton
2021
Escudería Puntos Victorias Podiums Poles Vueltas rápidas
Max Verstappen 395.5 10 18 10 6
Lewis Hamilton 387.5 8 17 5 6

Parrilla de pilotos

A continuación, puede verse lo que ha sido la parrilla de pilotos durante esta temporada, añadiendo al histórico piloto Robert Kúbica, que tuvo que sustutuir a Räikkönen durante un gran premio.


pilotos_2021 <- full_join(carreras, resultados, c("raceId" = "raceId") ) %>% 
  full_join(.,pilotos, c("driverId"="driverId")) %>% 
  filter(year=="2021") %>% 
  select(forename,surname, year) %>% distinct(forename,surname) %>% na.omit() %>% arrange(surname) %>% str_replace_all(., "é", "é") %>% str_replace_all(., "ä", "ä") %>% str_replace_all(., "ö", "ö")

nombres_normales <- c("Alonso", "Bottas", "Gasly", "Giovinazzi", "Hamilton", "Latifi", "Leclerc", "Mazepin", "Norris", "Ocon", "Pérez", "Räikkönen", "Ricciardo", "Russell", "Sainz", "Schumacher", "Stroll", "Tsunoda", "Verstappen", "Vettel")

pilotos_2021 <-  full_join(carreras, resultados, c("raceId" = "raceId") ) %>% 
  full_join(.,pilotos, c("driverId"="driverId")) %>% 
  filter(year=="2021") %>% 
  select(forename,surname, year) %>% distinct(forename,surname) %>% na.omit() %>% arrange(surname) %>% add_column(nombres_normales)  
 

# Pérez
# Räikkönen
fotos_pil_2021 <- c("./imagenes/pilotos/alonso.png", "./imagenes/pilotos/bottas.png", "./imagenes/pilotos/gasly.png", "./imagenes/pilotos/giovinazzi.jpg", "./imagenes/pilotos/hamilton.png", "./imagenes/pilotos/latifi.png", "./imagenes/pilotos/leclerc.png", "./imagenes/pilotos/mazepin.png", "./imagenes/pilotos/norris.png", "./imagenes/pilotos/ocon.jpg", "./imagenes/pilotos/perez.png", "./imagenes/pilotos/raikkonen.png", "./imagenes/pilotos/ricciardo.png", "./imagenes/pilotos/russell.png", "./imagenes/pilotos/sainz.png", "./imagenes/pilotos/mick.png", "./imagenes/pilotos/stroll.png", "./imagenes/pilotos/tsunoda.png", "./imagenes/pilotos/verstappen.jpg", "./imagenes/pilotos/vettel.png")

fotos_pais_2021 <- c("./imagenes/paises/espanya.png", "./imagenes/paises/finlandia.png", "./imagenes/paises/francia.png", "./imagenes/paises/italia.png","./imagenes/paises/uk.png", "./imagenes/paises/canada.png","./imagenes/paises/monaco.png", "./imagenes/paises/rusia.png","./imagenes/paises/uk.png", "./imagenes/paises/francia.png","./imagenes/paises/mexico.png", "./imagenes/paises/finlandia.png","./imagenes/paises/australia.png", "./imagenes/paises/uk.png","./imagenes/paises/espanya.png", "./imagenes/paises/alemania.png","./imagenes/paises/canada.png", "./imagenes/paises/japon.png","./imagenes/paises/holanda.png", "./imagenes/paises/alemania.png")

fotos_esc_2021 <- c("./imagenes/escuderias/alpine.png","./imagenes/escuderias/mercedes.png","./imagenes/escuderias/alphatauri.png", "./imagenes/escuderias/alfaromeo.jpg","./imagenes/escuderias/mercedes.png", "./imagenes/escuderias/williams.png","./imagenes/escuderias/ferrari.png", "./imagenes/escuderias/haas.png","./imagenes/escuderias/mclaren.png", "./imagenes/escuderias/alpine.png","./imagenes/escuderias/redbull.png", "./imagenes/escuderias/alfaromeo.jpg","./imagenes/escuderias/mclaren.png", "./imagenes/escuderias/williams.png","./imagenes/escuderias/ferrari.png", "./imagenes/escuderias/haas.png","./imagenes/escuderias/aston.png", "./imagenes/escuderias/alphatauri.png","./imagenes/escuderias/redbull.png", "./imagenes/escuderias/aston.png")

pilotos_2021 <- pilotos_2021 %>%
  add_column(fotos_pil_2021, fotos_pais_2021, fotos_esc_2021) %>% select(nombres_normales, fotos_pil_2021, fotos_pais_2021, fotos_esc_2021)


mundial_2021 <- pilotos_2021 %>% gt() %>% text_transform( locations = cells_body(columns = c(fotos_pil_2021)), fn = function(x) {gt::local_image(x, height = 100)}) %>% text_transform( locations = cells_body(columns = c(fotos_pais_2021)), fn = function(x) {gt::local_image(x, height = 50)}) %>% text_transform( locations = cells_body(columns = c(fotos_esc_2021)), fn = function(x) {gt::local_image(x, height = 70)}) %>% tab_header(title = md("**Pilotos 2021**"), subtitle = md("Parrilla")) %>%   cols_label(
    nombres_normales = html(""),
    fotos_pil_2021 = html(""),
    fotos_pais_2021 = html(""),
    fotos_esc_2021 = html("")) %>%  
  tab_options(table.background.color = "gray13",   table.font.color.light = "cyan") %>% 
  cols_align(align = "center",
  columns = everything())


mundial_2021
Pilotos 2021
Parrilla
Alonso
Bottas
Gasly
Giovinazzi
Hamilton
Latifi
Leclerc
Mazepin
Norris
Ocon
Pérez
Räikkönen
Ricciardo
Russell
Sainz
Schumacher
Stroll
Tsunoda
Verstappen
Vettel

La parrilla de pilotos de esta temporada 2021, va a sufrir una serie de cambios respecto a la temporada de 2022. Valteri Bottas abandona Mercedes y ocupa un asiento en Alfa Romeo. Este será sustituido en Mercedes por el piloto inglés de Williams, George Russel, que a su vez cede su hueco al ex- piloto de Red Bull Alex Albon. Como los pilotos Kimi Räikkönen y Antonio Giovinazzi abandonan la F1, sus puestos en el equipo Alfa Romeo, serán ocupados por Valteri Bottas, como he mencionado anteriormente y por Guanyu Zhou que será su compañero. El piloto chino, que ha disputado esta temporada el campeonato del mundo de Fórmula 2, procede de la academia de Alpine.

Templos

El siguiente globo terraqueo muestra todos los grandes premios de esta temporada, situandolos e indicando la ronda del mundial que son y el país donde se han celebrado.


globo_circ <-create_globe() %>% globe_pov(45.61560, 9.281110) %>% globe_bars(coords(lat, lng, label  = variables, color = round2), data = carreras_21_v2)  %>% scale_bars_color()
globo_circ

3.4 El nano

Fernando Alonso Díaz (Oviedo, Asturias; 29 de julio de 1981) es un piloto español de automovilismo de velocidad. Con dos títulos mundiales en su palmarés (Renault 2005 y 2006), diferentes estudios predictivos colocan a Alonso entre los mejores pilotos de la historia. Podía haber ganado mucho más, pero en ocasiones la elección del equipo no acompañó a su ambición.

Alonso vs compañeros de equipo

Alonso ha tenido 12 compañeros durante sus 17 temporadas. El piloto asturiano en todos estos años, solo ha quedado una vez por detrás de su compañero, y fue en 2015 con Button, durante la temporada horrible que llevo a cabo la escudería McLaren. En 2001 con Marques y en 2007 con Hamilton quedó empatado a puntos (en el caso de Marques ninguno puntúa), aunque ambos terminan por delante en la clasificación por mejor puesto final en carrera. Tiene 232 mejores puestos en carrera por 63 peores. Unos números que no son alcanzados ni por los mejores pilotos de la historia.

gc() 
#>            used  (Mb) gc trigger  (Mb) max used  (Mb)
#> Ncells  5030640 268.7    8723447 465.9  8723447 465.9
#> Vcells 17607604 134.4   33631647 256.6 33631640 256.6
ggalo_vs_all <- ggplot(data = ALO_VS_ALL, aes(round, puntos_acumulados, color = driverRef)) +
  geom_line() +
  geom_point() + 
  labs(title = "Alonso contra el mundo",
       subtitle = "Alonso VS cada compañero de equipo",
       y = "Puntos", x = "") + theme(axis.line = element_line(colour = "gray30",
    linetype = "solid"), axis.ticks = element_line(colour = "gray30"),
    panel.grid.major = element_line(colour = "gray20"),
    panel.grid.minor = element_line(linetype = "blank"),
    axis.title = element_text(size = 15,
        colour = "white"), axis.text = element_text(colour = "white"),
    plot.title = element_text(size = 20,
        colour = "white", hjust = 0.5), legend.text = element_text(colour = "white"),
    legend.title = element_text(colour = "white"),
    panel.background = element_rect(fill = "gray13",
        colour = "gray13", linetype = "solid"),
    plot.background = element_rect(fill = "gray13",
        colour = "gray13", linetype = "solid"),
    legend.key = element_rect(fill = "gray13",
        colour = "gray13"), legend.background = element_rect(fill = "gray13",
        colour = "gray13")) +labs(x = "Nº carrera", colour = "Piloto") + theme(plot.subtitle = element_text(size = 10,
    hjust = 0.5)) + facet_wrap( ~ year) #+ transition_reveal(round)

ggalo_vs_all

Alonso vs Hamilton

La rivalidad entre estos los dos plotos, más que conocida,puede observarse en la tabla que se decanta para el lado de Hanilton, ya que este tiene más campeonatos y más puntos, pero no significa ni mucho menos que sea mejor piloto.

Fernando Alonso y Lewis Hamilton llegaron juntos a McLaren en 2007. Uno era bicampeón del mundo de Fórmula 1 tras una etapa maravillosa en Renault, y el otro un recién llegado, con gran proyección. Su rivalidad desde entonces ha ido incrementando, debido a dos personalidades muy fuertes y competitivas.


#se necesita tener cargado "n_carreras_nom", "victorias_con_nombre"
#1234

alo_vs_ham_tabla <- alo_vs_ham %>% gt() %>% text_transform( locations = cells_body(columns = c(fotos_esp_ing)), fn = function(x) {gt::local_image(x, height = 50)}) %>% text_transform( locations = cells_body(columns = c(fotos_ALO_vs_HAM)), fn = function(x) {gt::local_image(x, height = 100)}) %>% tab_header(title = md("**Alonso vs Hamilton**"), subtitle = md("Comparación")) %>%   cols_label(
    driverRef = html(""),
    numero_carreras = html("Nº carreras"),
    n_victorias = html("Nº victorias"),
    fotos_esp_ing = html("País"),
    fotos_ALO_vs_HAM = html("")) %>%  
  tab_options(table.background.color = "gray13",   table.font.color.light = "cyan") %>% 
  cols_align(align = "center",
  columns = everything())

alo_vs_ham_tabla
Alonso vs Hamilton
Comparación
Nº carreras Nº victorias País
alonso 323 32
hamilton 275 98

4. Trabajos en los que te has basado

Con los datos que hemos encontrado, existen una serie de códigos que ya trabajan con estos datos, especialmente este, a partir del cual, sobre todo, nos hemos fijado en la estética de los gráficos y las imagenes con las que los acompañaba. También hemos obtenido ideas para trabajar los datos, pero en menor medida que el apartado visual, ya que el trabajo citado se centra unicamente en la temporada actual, mientras que Alt+ Formula 1 combina tanto la actualidad como la historia en general de la F1.

5. Bibliografía

Para la obtención de información de la historia de la f1 se ha usado esta página web.

Los datos a partir de los cuales se ha elaborado el df de muertes se han obtenido de esta página web.

Para la obtención de los datos de las audiencias se han utilizado tanto esta página web , como este post de twitter.

Para la elaboración del apartado de Fernando Alonso se han utilizado las siguientes páginas web: esta y esta.

LS0tDQp0aXRsZTogIkFsdCArIEZvcm11bGEgMSINCmF1dGhvcjogIkNheWV0YW5vIFJvbWVybyBNb250ZWFndWRvIChjYXJvbW9uM0BhbHVtbmkudXYuZXMpICBcblxuIEFsZWphbmRybyBHYXJjw61hIFNlZ2FycmEgKGFnYXJzZTRAYWx1bW5pLnV2LmVzKSAgXG4gXG4gQ2FybG9zIEdhcmPDrWEgQ2FzdGlsbGEgKGdhcmNhczhAYWx1bW5pLnV2LmVzKS4gXG5cbiBVbml2ZXJzaXRhdCBkZSBWYWzDqG5jaWEiDQpkYXRlOiAiRGljaWVtYnJlIGRlIDIwMjEgKGFjdHVhbGl6YWRvIGVsIGByIGZvcm1hdChTeXMudGltZSgpLCAnJWQtJW0tJVknKWApIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgICNjc3M6ICIuL2Fzc2V0cy9teV9jc3NfZmlsZS5jc3MiDQogICAgdGhlbWU6IGRhcmtseQ0KICAgIGhpZ2hsaWdodDogdGFuZ28gDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAzIA0KICAgIHRvY19mbG9hdDogDQogICAgICBjb2xsYXBzZWQ6IHRydWUNCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUNCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UNCiAgICBkZl9wcmludDoga2FibGUNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQplZGl0b3Jfb3B0aW9uczogDQogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlDQotLS0NCjwhLS0tIGNodW5rIHBhcmEgcXVlIGxhIGZ1ZW50ZSBzZWEgbGEgb2ZpY2lhbCBkZSBsYSBGb3JtdWxhIDEgLS0+DQpgYGB7Y3NzLCBlY2hvPUZBTFNFfSANCkBmb250LWZhY2Ugew0KICBmb250LWZhbWlseTogRjE7DQogIHNyYzogdXJsKGh0dHBzOi8vd3d3LmZvcm11bGExLmNvbS9ldGMvZGVzaWducy9mb20td2Vic2l0ZS9mb250cy9GMVJlZ3VsYXIvRm9ybXVsYTEtUmVndWxhci50dGYpOw0KfQ0KDQpzcGFuew0KICBmb250LWZhbWlseTogRjE7DQp9DQoNCmF7DQogIGZvbnQtZmFtaWx5OiBGMTsNCn0NCg0KLm5hdi1waWxscz5saS5hY3RpdmU+YTpmb2N1cyB7DQogICAgY29sb3I6ICNmZmZmZmY7DQogICAgYmFja2dyb3VuZC1jb2xvcjogbGlnaHRncmF5Ow0KfQ0KDQouY29udGFpbmVyLWZsdWlkLCAuY29udGFpbmVyLWZsdWlkIGgxIHsNCiAgICBmb250LWZhbWlseTogRjE7DQogICAgbGluZS1oZWlnaHQ6IDEuNzsNCn0NCg0KLmNvbnRhaW5lci1mbHVpZCBwIHsNCiAgICBmb250LWZhbWlseTogRjE7DQogICAgY29sb3I6Y3lhbjsNCn0NCg0KaDEsaDIsaDMsaDQsaDUsaDYscCwgdGFibGUgew0KICBmb250LWZhbWlseTogRjE7DQogIGNvbG9yOiBjeWFuDQp9DQpgYGANCg0KYGBge3IgY2h1bmstc2V0dXAsIGluY2x1ZGUgPSBGQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgZXZhbCA9IFRSVUUsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCANCiAgICAgICAgICAgICAgICAgICAgICAjcmVzdWx0cyA9ICJob2xkIiwNCiAgICAgICAgICAgICAgICAgICAgICBjYWNoZSA9IEZBTFNFLCBjYWNoZS5wYXRoID0gIi9jYWNoZXMvIiwgY29tbWVudCA9ICIjPiIsDQogICAgICAgICAgICAgICAgICAgICAgI2ZpZy53aWR0aCA9IDcsICNmaWcuaGVpZ2h0PSA3LCAgIA0KICAgICAgICAgICAgICAgICAgICAgICNvdXQud2lkdGggPSA3LCBvdXQuaGVpZ2h0ID0gNywNCiAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZSA9IFRSVUUsICBmaWcuc2hvdyA9ICJob2xkIiwNCiAgICAgICAgICAgICAgICAgICAgICBmaWcuYXNwID0gMC42MjgsIG91dC53aWR0aCA9ICI3NSUiLCBmaWcuYWxpZ24gPSAiY2VudGVyIikNCmtuaXRyOjpvcHRzX2NodW5rJHNldChkZXYgPSAicG5nIiwgZGV2LmFyZ3MgPSBsaXN0KHR5cGUgPSAiY2Fpcm8tcG5nIikpDQpgYGANCg0KYGBge3Igb3B0aW9ucy1zZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpICMtIHBhcmEgcXVpdGFyIGxhIG5vdGFjacOzbiBjaWVudMOtZmljYQ0Kb3B0aW9ucygieWFtbC5ldmFsLmV4cHIiID0gVFJVRSkgDQpgYGANCg0KDQpgYGB7ciBrbGlwcHksIGVjaG8gPSBGQUxTRX0NCmtsaXBweTo6a2xpcHB5KHBvc2l0aW9uID0gYygidG9wIiwgInJpZ2h0IikpICMtIHJlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCJybGVzdXIva2xpcHB5IikNCmBgYA0KDQo8ZGl2IHN0eWxlPSJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij48ZGl2Lz4NCg0KPGhyIGNsYXNzPSJsaW5lYS1ibGFjayI+DQoNCjwhLS0gRWwgcMOhcnJhZm8gZGUgYWJham8gaGFzIGRlIGRlamFybG8gY2FzaSBpZ3VhbCwgc29sbyBIQVMgZGUgU1VTVElUVUlSICJwZXJlenA0NCIgcG9yIHR1IHVzdWFyaW8gZGUgR2l0aHViLS0+DQpUcmFiYWpvIGVsYWJvcmFkbyBwYXJhIGxhIGFzaWduYXR1cmEgIlByb2dyYW1hY2nDs24geSBtYW5lam8gZGUgZGF0b3MgZW4gbGEgZXJhIGRlbCBCaWcgRGF0YSIgZGUgbGEgVW5pdmVyc2l0YXQgZGUgVmFsw6huY2lhIGR1cmFudGUgZWwgY3Vyc28gMjAyMS0yMDIyLiBFbCByZXBvIGRlbCB0cmFiYWpvIGVzdMOhIFthcXXDrV0oaHR0cHM6Ly9naXRodWIuY29tL2NheWV0YW5vMTA4L3RyYWJham9fQmlnRGF0YV9lcXVpcG8pe3RhcmdldD0iX2JsYW5rIn0uIA0KDQo8IS0tIEVsIHDDoXJyYWZvIGRlIGFiYWpvIGhhcyBkZSBkZWphcmxvIGV4YWN0YW1lbnRlIGlndWFsLCBOTyBoYXMgZGUgY2FtYmlhciBuYWRhLS0+DQoNCkxhIHDDoWdpbmEgd2ViIGRlIGxhIGFzaWduYXR1cmEgeSBsb3MgdHJhYmFqb3MgZGUgbWlzIGNvbXBhw7Flcm9zIHB1ZWRlbiB2ZXJzZSBbYXF1w61dKGh0dHBzOi8vcGVyZXpwNDQuZ2l0aHViLmlvL2ludHJvLWRzLTIxLTIyLXdlYi8wNy10cmFiYWpvcy5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9Lg0KDQo8aHIgY2xhc3M9ImxpbmVhLXJlZCI+DQoNCg0KDQo8IS0tTGlicmVyaWEgZGUgcGFxdWV0ZXMgLS0+DQpgYGB7ciBwYWNrYWdlcy1zZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0KbGlicmFyeShtZW1lKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGtsaXBweSkgICMtIHJlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCJybGVzdXIva2xpcHB5IikNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KHJpbykNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZ2dhbmltYXRlKQ0KbGlicmFyeShnZ1RoZW1lQXNzaXN0KQ0KbGlicmFyeShnbG9iZTRyKSAgI3JlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCJKb2huQ29lbmUvZ2xvYmU0ciIpDQpsaWJyYXJ5KHJlbW90ZXMpIA0KbGlicmFyeShndCkNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KHRyZWVtYXApICNpbnN0YWxsLnBhY2thZ2VzKHRyZWVtYXApDQpsaWJyYXJ5KGQzdHJlZVIpICNyZW1vdGVzOjppbnN0YWxsX2dpdGh1YigiZDN0cmVlUi9kM3RyZWVSIikNCmxpYnJhcnkobWFnaWNrKQ0KbGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeSh0bWFwKQ0KbGlicmFyeShmbGV4dGFibGUpDQpsaWJyYXJ5KG9mZmljZXIpDQpsaWJyYXJ5KHBuZykNCmxpYnJhcnkoZ3JpZCkNCmBgYA0KDQoNCiMgMS4gSW50cm9kdWNjacOzbg0KDQpMYSBGb3JtdWxhIDEgZXMgdW5vIGRlIGxvcyBkZXBvcnRlcy9lc3BlY3RhY3Vsb3MgIG3DoXMgaW1wb3J0YW50ZXMgZGVsIG11bmRvLCBsb2dyYW5kbyBhIGxvIGxhcmdvIGRlIHN1cyBoaXN0b3JpYSBjYXB0YXIgYSBtaWxsb25lcyB5IG1pbGxvbmVzIGRlIGVzcGVjdGFkb3Jlcy4gTnVldHJvIHRyYWJham8gcHJldGVuZGUgcGxhc21hciBsYSBncmFuZGV6YSBkZSBsYSBGw7NybXVsYSAxIGEgdHJhdsOpcyBkZSBkaXN0aW50b3MgZGF0b3MgcXVlIHB1ZWRlbiB2ZXJzZSBhIGxvIGxhcmdvIGRlbCB0cmFiYWpvLCB0YW50byBwcmVzZW50ZXMgY29tbyBwYXNhZG9zLiBBZGVtw6FzLCBwYXJ0ZSBkZWwgdHJhYmFqbyBzZSBoYSBjZW50cmFkbyBlbiBsYSBmaWd1cmEgZGUgRmVybmFuZG8gQWxvbnNvLCBlbCBwaWxvdG8gY29uIG1heW9yIGltcG9ydGFuY2lhIGVuIEVzcGHDsWEsIHkgdW5vIGRlIGxvcyBtw6FzIHJlbGV2YW50ZXMgZW4gbGEgaGlzdG9yaWEgZGUgbGEgRm9ybXVsYSAxLiAgDQpFbiByZWxhY2nDs24gY29uIGxhIGFzaWduYXR1cmEsIGxhIGVsZWNjacOzbiBkZWwgdGVtYSBzZSBkZWJlIGEgbG8gZnVuZGFtZW50YWwgcXVlIHNvbiBsb3MgZGF0b3MgZW4gZXN0ZSBkZXBvcnRlLCB0YW50byBwYXJhIGxhIGVsYWJvcmFjacOzbiBkZSBlc3RyYXRlZ2lhcywgZWwgZGlzZcOxbyBkZSBsb3MgY29jaGVzIG8gaW5jbHVzbyBkZSBsYXMgcGlzdGFzLiBEZWJpZG8gYSB0b2RhcyBlc3RhcyByYXpvbmVzLCBjcmVlbW9zIHF1ZSBsYSBGMSwgYSBwZXNhciBkZSBubyBzZXIgdW4gdGVtYSByZWxhY2lvbmFkbyBjb24gbGEgZWNvbm9tw61hLCBlbmNhamEgcGVyZmVjdGFtZW50ZSBjb24gbGEgYXNpZ25hdHVyYS4NCg0KIDxjZW50ZXI+KipUSEUgUExBTioqDQoNCmBgYHtyLCBldmFsPSBUUlVFLCBlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCg0KbXlfZm90byA8LSAiaHR0cHM6Ly9lMDAtZWxtdW5kby51ZWNkbi5lcy9hc3NldHMvbXVsdGltZWRpYS9pbWFnZW5lcy8yMDE3LzA1LzEyLzE0OTQ1ODk5MzQ2MzA2LmpwZyINCm1lbWUobXlfZm90bywgIlNFIFZJRU5FIFRSQUJBSkFaTyIsICJNVVkgVFJBTlFVSUxPUyIsIHNpemUgPSAyICwgY29sb3IgPSAiYmx1ZSIsIHZqdXN0ID0gMS4wNSkNCg0KYGBgDQoNCg0KDQojIDIuIERhdG9zDQoNCkhlbW9zIGVuY29udHJhZG8gZW4gW2thZ2dsZV0oaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS8pIGJhc3RhbnRlcyBjb25qdW50b3MgZGUgZGF0b3MgY29uIGxvcyBxdWUgcG9kZXIgdHJhYmFqYXIsIHBlcm8gZXNwZWNpYWxtZW50ZSBbZXN0ZV0oaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9yb2hhbnJhby9mb3JtdWxhLTEtd29ybGQtY2hhbXBpb25zaGlwLTE5NTAtMjAyMCksIHF1ZSBwb3NlZSBncmFuIHZhcmllZGFkIGRlIGRhdG9zIGVuIGxvIHJlZmVyZW50ZSBhIHBpbG90b3MsIHJlc3VsdGFkb3MsIGNpcmN1aXRvcywgdGllbXBvcywgZXRjLg0KDQoNCiMjIDIuMS4gUHJvY2VzYW5kbyBsb3MgZGF0b3MNCg0KQSBjb250aW51YWNpw7NuIHNlIG11ZXN0cmEgdG9kYSBsYSBtYW5pcHVsYWNpw7NuIGRlIGxvcyBkYXRvcywgYSBwYXJ0aXIgZGVsIGNvbmp1bnRvIGRlIGRhdG9zIG1vc3RyYWRvIGFudGVyaW9ybWVudGUsIHkgcXVlIHBvc3Rlcmlvcm1lbnRlIHNvbiB1dGlsaXphZG9zIHBhcmEgbGEgcmVhbGl6YWNpw7NuIGRlIGxvcyBkaXN0aW50YXMgcGFydGVzIHF1ZSBmb3JtYW4gZWwgdHJhYmFqby4NCg0KYGBge3IsIGV2YWwgPSBUUlVFLCBlY2hvID0gVFJVRX0NCg0KIy0tLVBSRVBBUkFDSU9OIERFIExPUyBEQVRPUw0KdGllbXBvcyA8LSByaW86OmltcG9ydChmaWxlID0gIi4vZGF0b3MvbGFwX3RpbWVzLmNzdiIpDQpwaWxvdG9zIDwtIHJpbzo6aW1wb3J0KGZpbGUgPSAiLi9kYXRvcy9kcml2ZXJzLmNzdiIpDQpyZXN1bHRhZG9zIDwtIHJpbzo6aW1wb3J0KGZpbGUgPSAiLi9kYXRvcy9yZXN1bHRzLmNzdiIpDQpjYXJyZXJhcyA8LSByaW86OmltcG9ydChmaWxlID0gIi4vZGF0b3MvcmFjZXMuY3N2IikNCmVzY3VkZXJpYXMgPC0gcmlvOjppbXBvcnQoZmlsZSA9ICIuL2RhdG9zL2NvbnN0cnVjdG9ycy5jc3YiKQ0KZXNjdWRlcmlhczIgPC0gcmlvOjppbXBvcnQoZmlsZSA9ICIuL2RhdG9zL2NvbnN0cnVjdG9yX3N0YW5kaW5ncy5jc3YiKQ0KcmVzdWx0X2VzY3VkZXJpYXMgPC0gcmlvOjppbXBvcnQoZmlsZSA9ICIuL2RhdG9zL2NvbnN0cnVjdG9yX3Jlc3VsdHMuY3N2IikNCmNpcmN1aXRvcyA8LSByaW86OmltcG9ydChmaWxlID0gIi4vZGF0b3MvY2lyY3VpdHMuY3N2IikNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiNjYXBpdHVsbyBvc2N1cm8gZGVsIGRlcG9ydGUNCiNjcmVvIGRmIGRlIG11ZXJ0ZXMgZGUgZm9ybXVsYSAxDQptdWVydGVzZjEgPC0gZGF0YS5mcmFtZSgNCiAgIm9yZGVuIiA9IDE6NDIsDQogICJkcml2ZXJSZWYiID0gYygiQ2hldCBNaWxsZXIiLCAiQ2FybCBTY2FyYWJvcm91Z2giLCAiT25vZnJlIE1hcmltb24iLCAiTWFubnkgQXl1bG8iLCAiQmlsbCBWdWtvdmljaCIsICJBbGJlcnRvIEFzY2FyaSIsIkV1Z2VuaW8gQ2FzdGVsbG90dGkiLCAiS2VpdGggQW5kcmV3cyIsICJQYXQgTydDb25ub3IiLCAiTHVpZ2kgTXVzc28iLCAiUGV0ZXIgQ29sbGlucyIsICJTdHVhcnQgTGV3aXMtRXZhbnMiLCAiSmVycnkgVW5zZXIiLCAiQm9iIENvcnRuZXIiLCAiSXZvciBCdWViIiwgIkNocmlzIEJyaXN0b3ciLCAiQWxhbiBTdGFjZXkiLCAiR2l1bGlvIENhYmlhbmNhIiwgIldvbGZnYW5nIHZvbiBUcmlwcyIsICJDYXJlbCBHb2RpbiBkZSBCZWF1Zm9ydCIsICJKb2huIFRheWxvciIsICJMb3JlbnpvIEJhbmRpbmkiLCAiQm9iIEFuZGVyc29uIiwgIkpvIFNjaGxlc3NlciIsICJHZXJoYXJkIE1pdHRlciIsICJQaWVycyBDb3VyYWdlIiwgIkpvY2hlbiBSaW5kdCIsICJKbyBTaWZmZXJ0IiwgIlJvZ2VyIFdpbGxpYW1zb24iLCAiRnJhbsOnb2lzIENldmVydCIsICJQZXRlciBSZXZzb24iLCAiSGVsbXV0aCBLb2luaWdnIiwgIk1hcmsgRG9ub2h1ZSIsICJUb20gUHJ5Y2UiLCAiUm9ubmllIFBldGVyc29uIiwgIlBhdHJpY2sgRGVwYWlsbGVyIiwgIkdpbGxlcyBWaWxsZW5ldXZlIiwgIlJpY2NhcmRvIFBhbGV0dGkiLCAiRWxpbyBkZSBBbmdlbGlzIiwgIlJvbGFuZCBSYXR6ZW5iZXJnZXIiLCAiQXlydG9uIFNlbm5hIiwgIkp1bGVzIEJpYW5jaGkiKSwNCiAgIm5hdGlvbmFsaXR5IiA9IGMoIkFtZXJpY2FuIiwgIkFtZXJpY2FuIiwgIkFyZ2VudGluZSIsICJBbWVyaWNhbiIsICJBbWVyaWNhbiIsICJJdGFsaWFuIiwiSXRhbGlhbiIsICJBbWVyaWNhbiIsICJBbWVyaWNhbiIsICJJdGFsaWFuIiwgIkJyaXRpc2giLCAiQnJpdGlzaCIsICJBbWVyaWNhbiIsICJBbWVyaWNhbiIsICJCcml0aXNoIiwgIkJyaXRpc2giLCAiQnJpdGlzaCIsICJJdGFsaWFuIiwgIkdlcm1hbiIsICJEdXRjaCIsICJCcml0aXNoIiwgIkl0YWxpYW4iICwgIkJyaXRpc2giLCAiRnJlbmNoIiwgIkdlcm1hbiIsICJCcml0aXNoIiwgIkF1c3RyaWFuIiwgIlN3aXNzIiwgIkJyaXRpc2giLCAiRnJlbmNoIiwgIkFtZXJpY2FuIiwgIkF1c3RyaWFuIiwgIkFtZXJpY2FuIiwgIkJyaXRpc2giLCAiU3dlZGlzaCIsICJGcmVuY2giLCAiQ2FuYWRpYW4iLCAiSXRhbGlhbiIsICJJdGFsaWFuIiwgIkF1c3RyaWFuIiwgIkJyYXppbGlhbiIsICJGcmVuY2giKSwNCiAgImZlY2hhX211ZXJ0ZSIgPSBjKDE5NTMsIDE5NTMsIDE5NTQsIDE5NTUsIDE5NTUsIDE5NTUsIDE5NTcsIDE5NTcsIDE5NTgsMTk1OCwxOTU4LDE5NTgsMTk1OSwxOTU5LDE5NTksMTk2MCwgMTk2MCwxOTYxLDE5NjEsMTk2NCwxOTY2LCAxOTY3LCAxOTY3LDE5NjgsMTk2OSwgMTk3MCwxOTcwLDE5NzEsMTk3MywxOTczLDE5NzQsMTk3NCwxOTc1LDE5NzcsMTk3OCwxOTgwLDE5ODIsMTk4MiwxOTg2LDE5OTQsMTk5NCwyMDE0KSkNCiNubyBwb25nbyBsYXMgY29taWxsYXMgZW4gbG9zIGHDsW9zIHBhcmEgcXVlIHNlIGNyZWVuIGRpcmVjdGFtZW50ZSBjb21vIG9ic2VydmFjaW9uZXMgbnVtZXJpY2FzDQoNCiNjcmVvIHVuIGRmIGNvbiB0b2RvcyBsb3MgYcOxb3MgcGFyYSBsdWVnbyBmdXNpb25hcmxvLCB5YSBxdWUgbm8gaGF5IG11ZXJ0ZXMgdG9kb3MgbG9zIGHDsW9zIA0KYW55b3MgPC0gZGF0YS5mcmFtZSgNCiAgIm9yZGVuIiA9IDE6NzEsDQogICJhw7FvIiA9IGMoMTk1MDoyMDIwKSkNCg0KI3N1bWF0b3JpbyBkZSBsYXMgbXVlcnRlcyBwb3IgYcOxbw0KbXVlcnRlc19hbnlvIDwtIG11ZXJ0ZXNmMSAlPiUgZ3JvdXBfYnkoZmVjaGFfbXVlcnRlKSAlPiUgbXV0YXRlKG11ZXJ0ZXN4YW55byA9IHN1bShuKCkpKSAlPiUgZGlzdGluY3QoZmVjaGFfbXVlcnRlLCBtdWVydGVzeGFueW8pIA0KDQojZnVzaW9ubyBsb3MgMiBkZnMgcGFyYSBxdWUgdGVuZ2EgZW4gY3VlbnRhIGxvcyBhw7FvcyBkb25kZSBubyBoYXkgbXVlcnRlcw0KbXVlcnRlc2YxX2ZpbmFsIDwtIGZ1bGxfam9pbihtdWVydGVzX2FueW8sIGFueW9zLCBjKCJmZWNoYV9tdWVydGUiID0gImHDsW8iKSkgJT4lIHNlbGVjdChmZWNoYV9tdWVydGUsbXVlcnRlc3hhbnlvKSAlPiUgYXJyYW5nZShmZWNoYV9tdWVydGUpDQoNCiNjb252aWVydG8gbG9zIE4vQSBlbiAwLCBlcyBkZWNpciwgY3VhbmRvIG5vIGhheSBvYnNlcnZhY2lvbmVzLCBoYSBoYWJpZG8gMCBtdWVydGVzDQptdWVydGVzZjFfZmluYWxbaXMubmEobXVlcnRlc2YxX2ZpbmFsKV0gPC0gMA0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojc3RyKHJlc3VsdGFkb3MpDQojc3RyKHBpbG90b3MpDQojcGlsb3Rvc1ssIGMoMSldIDwtIHNhcHBseShwaWxvdG9zWywgYygxKV0sIGFzLm51bWVyaWMpDQojcmVzdWx0YWRvc1ssIGMoMyw2LDkpXSA8LSBzYXBwbHkocmVzdWx0YWRvc1ssIGMoMyw2LDkpXSwgYXMubnVtZXJpYykNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KI251bWVybyBkZSBjYXJyZXJhcyBxdWUgaGEgY29ycmlkbyBjYWRhIHBpbG90bw0KDQpuX2NhcnJlcmFzIDwtIHJlc3VsdGFkb3MgJT4lIGdyb3VwX2J5KGRyaXZlcklkKSAlPiUgbXV0YXRlKG51bWVyb19jYXJyZXJhcyA9IHN1bShuKCkpKSAlPiUgZGlzdGluY3QobnVtZXJvX2NhcnJlcmFzKSAlPiUgYXJyYW5nZShkZXNjKG51bWVyb19jYXJyZXJhcykpIA0KDQpuX2NhcnJlcmFzX25vbSA8LSBmdWxsX2pvaW4obl9jYXJyZXJhcywgcGlsb3RvcywgYyAoImRyaXZlcklkIiA9ICJkcml2ZXJJZCIpKSAlPiUgc2VsZWN0KGRyaXZlcklkLCBkcml2ZXJSZWYsIG51bWVyb19jYXJyZXJhcykgICU+JSAgZmlsdGVyKG51bWVyb19jYXJyZXJhcyA+PSAyMDIgKSAjbG9zIDIwIHFxdWUgbWFzIGNhcnJlcmFzIHRpZW5lbiAobm8gZnVuY2lvbmEgdXNhciBzbGljZV9tYXgpDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KI25hY2lvbmFsaWRhZCBkZSBsb3MgcGlsb3RvcyBhIGxvIGxhcmdvIGRlIGxhIGhpc3RvcmlhIA0KI21hcGENCm5hY2lvbmFsaWRhZCA8LSBwaWxvdG9zICU+JSBncm91cF9ieShuYXRpb25hbGl0eSkgJT4lIG11dGF0ZShudW1lcm9fY29tcGF0cmlvdGFzID0gc3VtKG4oKSkpICU+JSBkaXN0aW5jdChudW1lcm9fY29tcGF0cmlvdGFzKSAlPiUgYXJyYW5nZShkZXNjKG51bWVyb19jb21wYXRyaW90YXMpKSAlPiUgDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiQnJpdGlzaCIsICJVbml0ZWQgS2luZ2RvbSIpICU+JSANCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJBbWVyaWNhbiIsICJVbml0ZWQgU3RhdGVzIikgJT4lIA0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIkl0YWxpYW4iLCAnSXRhbHknKSAlPiUgDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiRnJlbmNoIiAsICdGcmFuY2UnKSAlPiUgDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiR2VybWFuIiAsICdHZXJtYW55JykgJT4lIA0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIkJyYXppbGlhbiIgLCAnQnJhemlsJykgJT4lIA0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIkFyZ2VudGluZSIgLCAnQXJnZW50aW5hJykgJT4lIA0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIlN3aXNzIiAsICdTd2l0emVybGFuZCcpICU+JSANCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJCZWxnaWFuIiAsICdCZWxnaXVtJykgJT4lIA0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIlNvdXRoIEFmcmljYW4iICwgJ1NvdXRoIEFmcmljYScpICU+JSANCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJKYXBhbmVzZSIgLCAnSmFwYW4nKSAlPiUgDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiQXVzdHJhbGlhbiIgLCAnQXVzdHJhbGlhJykgJT4lDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiRHV0Y2giICwgJ05ldGhlcmxhbmRzJykgJT4lDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiU3BhbmlzaCIgLCAnU3BhaW4nKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJBdXN0cmlhbiIgLCAnQXVzdHJpYScpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIkNhbmFkaWFuIiAsICdDYW5hZGEnKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJTd2VkaXNoIiAsICdTd2VkZW4nKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJGaW5uaXNoIiAsICdGaW5sYW5kJykgJT4lDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiTmV3IFplYWxhbmRlciIgLCAnTmV3IFplYWxhbmQnKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJNZXhpY2FuIiAsICdNZXhpY28nKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJJcmlzaCIgLCAnSXJlbGFuZCcpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIkRhbmlzaCIgLCAnRGVubWFyaycpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIlBvcnR1Z3Vlc2UiICwgJ1BvcnR1Z2FsJykgJT4lDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiTW9uZWdhc3F1ZSIgLCAnRnJhbmNlJykgJT4lDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiUmhvZGVzaWFuIiAsICdaaW1iYWJ3ZScpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIlVydWd1YXlhbiIgLCAnVXJ1Z3VheScpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIlJ1c3NpYW4iICwgJ1J1c3NpYScpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIkNvbG9tYmlhbiIgLCAnQ29sb21iaWEnKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJWZW5lenVlbGFuIiAsICdWZW5lenVlbGEnKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJFYXN0IEdlcm1hbiIgLCAnR2VybWFuJykgJT4lDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiSW5kaWFuIiAsICdJbmRpYScpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIlRoYWkiICwgJ1RoYWlsYW5kJykgJT4lDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiUG9saXNoIiAsICdQb2xhbmQnKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJNb25lZ2FzcXVlIiAsICdGcmFuY2UnKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJIdW5nYXJpYW4iICwgJ0h1bmdhcnknKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJDemVjaCIgLCAnQ3plY2ggUmVwLicpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIk1hbGF5c2lhbiIgLCAnTWFsYXlzaWEnKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJDaGlsZWFuIiAsICdDaGlsZScpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIkxpZWNodGVuc3RlaW5lciIgLCAnU3dpdHplcmxhbmQnKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJBbWVyaWNhbi1JdGFsaWFuIiAsICdVbml0ZWQgU3RhdGVzJykgJT4lDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiQXJnZW50aW5lLUl0YWxpYW4iICwgJ0FyZ2VudGluYScpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIkluZG9uZXNpYW4iICwgJ0luZG9uZXNpYScpDQoNCnBhaXNlc19ub3JtYWxlcyA8LSBjKCJVbml0ZWQgS2luZ2RvbSIsICJVbml0ZWQgU3RhdGVzIiwgIkl0YWx5IiwgIkZyYW5jZSIsICJHZXJtYW55IiwgIkJyYXppbCIsICJBcmdlbnRpbmEiLCAiU3dpdHplcmxhbmQiLCAiQmVsZ2l1bSIsICJTb3V0aCBBZnJpY2EiLCAiSmFwYW4iLCAiQXVzdHJhbGlhIiwgIk5ldGhlcmxhbmRzIiwgIlNwYWluIiwgIkF1c3RyaWEiLCAiQ2FuYWRhIiwgIlN3ZWRlbiIsICJGaW5sYW5kIiwgIk5ldyBaZWFsYW5kIiwgIk1leGljbyIsICJJcmVsYW5kIiwgIkRlbm1hcmsiLCAiUG9ydHVnYWwiLCAiRnJhbmNlIiwgIlppbWJhYndlIiwgIlVydWd1YXkiLCAiUnVzc2lhIiwgIkNvbG9tYmlhIiwgIlZlbmV6dWVsYSIsICJHZXJtYW55IiwgIkluZGlhIiwgIlRoYWlsYW5kIiwgIlBvbGFuZCIsICJIdW5nYXJ5IiwgIkN6ZWNoIFJlcC4iLCAiTWFsYXlzaWEiLCAiQ2hpbGUiLCAiU3dpdHplcmxhbmQiLCAiVW5pdGVkIFN0YXRlcyIsICJBcmdlbnRpbmEiLCAiSW5kb25lc2lhIiApDQoNCm5hY2lvbmFsaWRhZCA8LSBwaWxvdG9zICU+JSBncm91cF9ieShuYXRpb25hbGl0eSkgJT4lIA0KICBtdXRhdGUobnVtZXJvX2NvbXBhdHJpb3RhcyA9IHN1bShuKCkpKSAlPiUgDQogIGRpc3RpbmN0KG51bWVyb19jb21wYXRyaW90YXMpICU+JSANCiAgYXJyYW5nZShkZXNjKG51bWVyb19jb21wYXRyaW90YXMpKSAlPiUgDQogIGFkZF9jb2x1bW4ocGFpc2VzX25vcm1hbGVzKSAlPiUgIA0KICBncm91cF9ieShwYWlzZXNfbm9ybWFsZXMpICU+JSANCiAgbXV0YXRlKHRvdGFsX3BpbG90b3MgPSBzdW0obnVtZXJvX2NvbXBhdHJpb3RhcykpICU+JSAgDQogIGRpc3RpbmN0KHBhaXNlc19ub3JtYWxlcywgdG90YWxfcGlsb3RvcykNCg0KZGF0YShXb3JsZCkNCndvcmxkIDwtIFdvcmxkOyBybShXb3JsZCkNCg0Kd29ybGQgPC0gd29ybGRbISh3b3JsZCRuYW1lICVpbiUgYygnR3JlZW5sYW5kJywgJ0FudGFyY3RpY2EnKSksXQ0KDQpwaWxvdG9zX3Bvcl9wYWlzZXMgPC0gZnVsbF9qb2luKG5hY2lvbmFsaWRhZCwgd29ybGQsIGMoICJwYWlzZXNfbm9ybWFsZXMiID0gIm5hbWUiKSkgDQoNCnBpbG90b3NfcG9yX3BhaXNlcyRjb3VudHJ5IDwtIE5VTEwNCg0KcGlsb3Rvc19wb3JfcGFpc2VzW2lzLm5hKHBpbG90b3NfcG9yX3BhaXNlcyldIDwtIDANCg0KZ2dfcGlsb3Rvc19wb3JfcGFpc2VzIDwtIGdncGxvdChkYXRhID0gcGlsb3Rvc19wb3JfcGFpc2VzLCBhZXMoZ2VvbWV0cnkgPSBnZW9tZXRyeSkpICsgZ2VvbV9zZigpICsNCiAgICAgICBsYWJzKHRpdGxlID0gIlBpbG90b3MgcG9yIHBhw61zIiwNCiAgICAgICAgICAgIGNhcHRpb24gPSAiTWVub3IgaW50ZW5zaWRhZCBkZSBjb2xvciBlbiBhcXVlbGxvcyBwYWlzZXMgY29uIG3DoXMgcGlsb3RvcyIpDQoNCmdnX3BpbG90b3NfcG9yX3BhaXNlcyA8LSBnZ19waWxvdG9zX3Bvcl9wYWlzZXMgKyANCiAgZ2VvbV9zZihhZXMoZmlsbCA9IHRvdGFsX3BpbG90b3MpKSArIA0KICB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJ3aGl0ZSIpLA0KICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAid2hpdGUiKSwNCiAgICBheGlzLnRpY2tzID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gImJsYW5rIiksDQogICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJibGFuayIpLA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAiYmxhbmsiKSwNCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gImdyYXkxMyIpLA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLA0KICAgICAgICBjb2xvdXIgPSAid2hpdGUiLCBoanVzdCA9IDAuNSksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJ3aGl0ZSIpLA0KICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAid2hpdGUiKSwNCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTEzIiksDQogICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTEzIiksDQogICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiKSkgK2xhYnMoZmlsbCA9ICJOwqogZGUgcGlsb3RvcyIpICsgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiZ3JheTEzIiksDQogICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJncmF5MTMiKSkgKyB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9IE5BKSwNCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGxpbmV0eXBlID0gInNvbGlkIiksDQogICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGxpbmV0eXBlID0gInNvbGlkIikpICsgc2NhbGVfZmlsbF9ncmFkaWVudDIobG93ID0gIndoaXRlIiwgbWlkID0gInBpbmsiLCBoaWdoID0gInJlZCIsIG1pZHBvaW50ID0gLjAyKQ0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIG51bWVybyBkZSB2aWN0b3JpYXMgcG9yIHBpbG90bw0KdmljdG9yaWFzIDwtIHJlc3VsdGFkb3MgJT4lIGZpbHRlcihwb3NpdGlvbiA9PSAiMSIpICU+JSANCiAgZ3JvdXBfYnkoZHJpdmVySWQpICU+JSANCiAgbXV0YXRlKG5fdmljdG9yaWFzID0gc3VtKG4oKSkpICU+JSANCiAgZGlzdGluY3Qobl92aWN0b3JpYXMpICU+JSANCiAgYXJyYW5nZShkZXNjKG5fdmljdG9yaWFzKSkNCg0KI2FxdWkgZnVzaW9ubyBjb24gZWwgZGYgZGUgcGlsb3RvcyBwYXJhIHF1ZSBhcGFyZXpjYSBlbCBub21icmUgeSBubyBzw7NsbyBlbCBJRCBkZWwgcGlsb3RvIGVuIGN1ZXN0aW9uLCB5IGhhZ28gbG8gbWlzbW8gcXVlIGVuIGVsIGFwYXJ0YWRvIGRlIGFycmliYSBwYXJhIG9yZGVuYXINCnZpY3Rvcmlhc19jb25fbm9tYnJlIDwtIGZ1bGxfam9pbih2aWN0b3JpYXMsIHBpbG90b3MsIGMgKCJkcml2ZXJJZCIgPSAiZHJpdmVySWQiKSkgJT4lIA0KICBzZWxlY3QoZHJpdmVySWQsIG5hdGlvbmFsaXR5LCBkcml2ZXJSZWYsIG5fdmljdG9yaWFzKSAgDQptYXNfdmljdG9yaWFzIDwtIHZpY3Rvcmlhc19jb25fbm9tYnJlICU+JSAgZmlsdGVyKG5fdmljdG9yaWFzID49IDI1ICkgDQoNCiN2aWN0b3JpYXMgMg0KdmljdG9yaWFzMiA8LSBmdWxsX2pvaW4ocGlsb3RvcywgcmVzdWx0YWRvcywgYygiZHJpdmVySWQiID0gImRyaXZlcklkIikpICU+JSANCiAgZnVsbF9qb2luKC4sIGNhcnJlcmFzLCBjKCJyYWNlSWQiID0gInJhY2VJZCIpKSAlPiUgDQogIHNlbGVjdChkcml2ZXJJZCwgZHJpdmVyUmVmLCBwb3NpdGlvbiwgeWVhciwgZGF0ZSkgJT4lIA0KICBmaWx0ZXIocG9zaXRpb24gPT0gMSkgJT4lIA0KICBncm91cF9ieShkcml2ZXJSZWYpICU+JSANCiAgbXV0YXRlKHZpY3RvcmlhX251bSA9IHN1bSggTk4gPSBuKCkpKSAlPiUgDQogIGZpbHRlcih2aWN0b3JpYV9udW0gPj0gMjApICU+JSANCiAgYXJyYW5nZSh2aWN0b3JpYV9udW0sIGRhdGUpICU+JSANCiAgbXV0YXRlKCBzdW1hX3ZpYyA9IGN1bXN1bShwb3NpdGlvbikpDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiNyZXN1bHRhZG8gbWVkaW8NCg0KcmVzdWx0YWRvc1ssIGMoNyldIDwtIHNhcHBseShyZXN1bHRhZG9zWywgYyg3KV0sIGFzLm51bWVyaWMpDQpyZXN1bHRhZG9zW2lzLm5hKHJlc3VsdGFkb3MpXSA8LSAyNSANCg0KI3Jlc3VsdGFkb19tZWRpbyA8LSAgZnVsbF9qb2luKHBpbG90b3MsIHJlc3VsdGFkb3MsICBjICgiZHJpdmVySWQiID0gImRyaXZlcklkIikpICU+JSANCiNzZWxlY3QoZHJpdmVySWQsIGRyaXZlclJlZiwgcG9zaXRpb24pICU+JSANCiAjIGdyb3VwX2J5KGRyaXZlcklkKSAlPiUgDQogICNtdXRhdGUocmVzdWx0X21lZGlvID0gbWVhbihwb3NpdGlvbikpICU+JSANCiAgI2Rpc3RpbmN0IChkcml2ZXJJZCwgZHJpdmVyUmVmLCByZXN1bHRfbWVkaW8pICU+JSBhcnJhbmdlKHJlc3VsdF9tZWRpbykNCg0KI3Jlc3VsdGFkbyBtZWRpbyBlbiBjbGFzaWZpY2FjaW9uDQpyZXN1bHRhZG9fbWVkaW9fY2xhcyA8LSAgZnVsbF9qb2luKHBpbG90b3MsIHJlc3VsdGFkb3MsICBjICgiZHJpdmVySWQiID0gImRyaXZlcklkIikpICU+JSANCiAgc2VsZWN0KGRyaXZlcklkLCBkcml2ZXJSZWYsIGdyaWQpICU+JSANCiAgZ3JvdXBfYnkoZHJpdmVySWQpICU+JSANCiAgbXV0YXRlKHJlc3VsdF9tZWRpb19jbGFzID0gbWVhbihncmlkKSkgJT4lIA0KICBkaXN0aW5jdCAoZHJpdmVySWQsIGRyaXZlclJlZiwgcmVzdWx0X21lZGlvX2NsYXMpICAlPiUgDQogIGZpbHRlcihyZXN1bHRfbWVkaW9fY2xhcyA+IDApICU+JSANCiAgYXJyYW5nZShyZXN1bHRfbWVkaW9fY2xhcykgIA0KDQoNCiNudW1lcm8gZGUgdnVlbHRhcyBsaWRlcmFuZG8NCg0KDQojcHVudG9zIHBvciBjYXJyZXJhIChwdW50b3MvY2FycmVyYSkNCg0KcHVudG9zX3hfY2FycmVyYSA8LSAgZnVsbF9qb2luKHBpbG90b3MsIHJlc3VsdGFkb3MsICBjICgiZHJpdmVySWQiID0gImRyaXZlcklkIikpICU+JSBzZWxlY3QoZHJpdmVySWQsIGRyaXZlclJlZiwgcG9pbnRzKSAlPiUgZnVsbF9qb2luKC4sIG5fY2FycmVyYXMsICBjICgiZHJpdmVySWQiID0gImRyaXZlcklkIikpICU+JSBncm91cF9ieShkcml2ZXJJZCkgJT4lIG11dGF0ZSh0b3RhbF9wdW50b3MgPSBzdW0ocG9pbnRzKSkgJT4lIGRpc3RpbmN0KGRyaXZlcklkLCBkcml2ZXJSZWYsIG51bWVyb19jYXJyZXJhcywgdG90YWxfcHVudG9zKSAlPiUgbXV0YXRlKG1lZGlhX3B1bnRvcyA9IHRvdGFsX3B1bnRvcy9udW1lcm9fY2FycmVyYXMpICU+JSBhcnJhbmdlKGRlc2MobWVkaWFfcHVudG9zKSkNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiNyZW1vbnRhZGFzDQoNCiNtYXMgcG9zaWNpb25lcyByZW1vbnRhZGFzIGVuIHVuYSBjYXJyZXJhIGdyYW4gcHJlbWlvDQoNCg0KcmVzdWx0YWRvc1ssIGMoNiw5KV0gPC0gc2FwcGx5KHJlc3VsdGFkb3NbLCBjKDYsOSldLCBhcy5udW1lcmljKSAjdHJhbnNmb3JtbyB2YXJpYWJsZXMgZ3JpZCB5IHBvc2l0aW9uT3JkZXIgZW4gbnVtZXJpY28NCnN0cihyZXN1bHRhZG9zKSAjIHBhcmEgY29tcHJvYmFybG8NCg0KDQojbWF5b3JlcyByZW1vbnRhZGFzIGRlIGxhIGhpc3RvcmlhLCBzZSByZXN0YSBwb3NpY2lvbiBkZSBzYWxpZGEgLSBwb3NpY2lvbiBmaW5hbA0KcHVlc3Rvc19yZW1vbnRhZG9zIDwtIHJlc3VsdGFkb3MgJT4lIG11dGF0ZShyZW1vbnRhZG9zID0gZ3JpZCAtIHBvc2l0aW9uT3JkZXIpICU+JSANCiAgc2VsZWN0KHJhY2VJZCwgZHJpdmVySWQsIGdyaWQsIHBvc2l0aW9uT3JkZXIsIHJlbW9udGFkb3MpIA0KDQoNCiNkZSB0b2RhIGxhIGhpc3RvcmlhDQpjaXJjdWl0b3NfZ3AgPC0gZnVsbF9qb2luKGNhcnJlcmFzLCBjaXJjdWl0b3MsIGMoImNpcmN1aXRJZCIgPSAiY2lyY3VpdElkIikpICU+JSANCiAgc2VsZWN0KGNpcmN1aXRJZCwgbmFtZS55LCByYWNlSWQsIHllYXIpDQoNCnB0b3NfcmVtb250X2NhcnJlcmEgPC0gaW5uZXJfam9pbihwdWVzdG9zX3JlbW9udGFkb3MsIGNpcmN1aXRvc19ncCkNCg0KcHVlc3Rvc19yZW1vbnRfcGlsb3RvIDwtIGZ1bGxfam9pbihwaWxvdG9zLCBwdG9zX3JlbW9udF9jYXJyZXJhLCBjKCJkcml2ZXJJZCIgPSAiZHJpdmVySWQiKSkgJT4lIA0KICBzbGljZV9tYXgocmVtb250YWRvcywgbj0xMCkgJT4lIA0KICBzZWxlY3QoZHJpdmVySWQsIGRyaXZlclJlZixuYW1lLnkseWVhciwgcmFjZUlkLCBncmlkLCBwb3NpdGlvbk9yZGVyLCByZW1vbnRhZG9zKQ0KDQojIGRlIGxhIGhpc290b3JpYSByZWNpZW50ZQ0KY2lyY3VpdG9zX2dwX3JlY2llbnQgPC0gZnVsbF9qb2luKGNhcnJlcmFzLCBjaXJjdWl0b3MsIGMoImNpcmN1aXRJZCIgPSAiY2lyY3VpdElkIikpICU+JSANCiAgc2VsZWN0KGNpcmN1aXRJZCwgbmFtZS55LCByYWNlSWQsIHllYXIpICU+JSANCiAgZmlsdGVyKHllYXIgPj0gMTk5NSkNCg0KcHRvc19yZW1vbnRfY2FycmVyYV9yZWNpZW50IDwtIGlubmVyX2pvaW4ocHVlc3Rvc19yZW1vbnRhZG9zLCBjaXJjdWl0b3NfZ3BfcmVjaWVudCkNCg0KcHVlc3Rvc19yZW1vbnRfcGlsb3RvX3JlY2llbnQgPC0gZnVsbF9qb2luKHBpbG90b3MsIHB0b3NfcmVtb250X2NhcnJlcmFfcmVjaWVudCwgYygiZHJpdmVySWQiID0gImRyaXZlcklkIikpICU+JSANCiAgc2xpY2VfbWF4KHJlbW9udGFkb3MsIG49MTApICU+JSANCiAgc2VsZWN0KGRyaXZlcklkLCBkcml2ZXJSZWYsIG5hbWUueSwgeWVhcixyYWNlSWQsIGdyaWQsIHBvc2l0aW9uT3JkZXIsIHJlbW9udGFkb3MpICU+JSANCiAgc2xpY2UoMTo0LDY6OCwxMCkgJT4lIA0KICBhcnJhbmdlKGRlc2MocmVtb250YWRvcykpDQoNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojbXVuZGlhbGVzIHBvciBuYWlvbmFsaWRhZCB5IHBpbG90bw0KY2FtcGVvbmVzIDwtIGZ1bGxfam9pbihwaWxvdG9zLCByZXN1bHRhZG9zLCBjKCJkcml2ZXJJZCIgPSAiZHJpdmVySWQiKSkgJT4lIA0KICBmdWxsX2pvaW4oLiwgY2FycmVyYXMsIGMoInJhY2VJZCIgPSAicmFjZUlkIikpICU+JSANCiAgc2VsZWN0KGRyaXZlcklkLCBkcml2ZXJSZWYsIG5hdGlvbmFsaXR5LCBjb25zdHJ1Y3RvcklkLCBwb2ludHMsIHllYXIsIHJvdW5kKSAlPiUgDQogIGZ1bGxfam9pbiguLCBlc2N1ZGVyaWFzLCBjKCJjb25zdHJ1Y3RvcklkIiA9ICJjb25zdHJ1Y3RvcklkIikpICU+JSANCiAgc2VsZWN0KGRyaXZlcklkLCBkcml2ZXJSZWYsIG5hdGlvbmFsaXR5LngsIGNvbnN0cnVjdG9ySWQsIHBvaW50cywgeWVhciwgbmFtZSwgcm91bmQpICU+JSAgDQogIGdyb3VwX2J5KHllYXIsIGRyaXZlclJlZikgJT4lICANCiAgbXV0YXRlKHB1bnRvc190b3RhbGVzID0gY3Vtc3VtKHBvaW50cykpICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgZ3JvdXBfYnkoeWVhcikgJT4lIA0KICBzbGljZV9tYXgocHVudG9zX3RvdGFsZXMsIG49MSkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIGdyb3VwX2J5KGRyaXZlclJlZikgJT4lIA0KICBtdXRhdGUodG90YWxfY2FtcGVvbmF0b3MgPSBzdW0oTk4gPSBuKCkpKSAlPiUgDQogIGRpc3RpbmN0KGRyaXZlclJlZiwgbmF0aW9uYWxpdHkueCwgdG90YWxfY2FtcGVvbmF0b3MpICU+JSANCiAgYXJyYW5nZShuYXRpb25hbGl0eS54LCB0b3RhbF9jYW1wZW9uYXRvcykNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiN0ZW1wb3JhZGEgMjAyMSB0YWJsYQ0KDQpwaWxvdG9zXzIwMjEgPC0gZnVsbF9qb2luKGNhcnJlcmFzLCByZXN1bHRhZG9zLCBjKCJyYWNlSWQiID0gInJhY2VJZCIpICkgJT4lIA0KICBmdWxsX2pvaW4oLixwaWxvdG9zLCBjKCJkcml2ZXJJZCI9ImRyaXZlcklkIikpICU+JSANCiAgZmlsdGVyKHllYXI9PSIyMDIxIikgJT4lIA0KICBzZWxlY3QoZm9yZW5hbWUsc3VybmFtZSwgeWVhcikgJT4lIA0KICBkaXN0aW5jdChmb3JlbmFtZSxzdXJuYW1lKSAlPiUgDQogIG5hLm9taXQoKSAlPiUgDQogIGFycmFuZ2Uoc3VybmFtZSkgJT4lIA0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIsODwqkiLCAiw6kiKSAlPiUgDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiw4PCpCIsICLDpCIpICU+JSANCiAgc3RyX3JlcGxhY2VfYWxsKC4sICLDg8K2IiwgIsO2IikNCg0Kbm9tYnJlc19ub3JtYWxlcyA8LSBjKCJBbG9uc28iLCAiQm90dGFzIiwgIkdhc2x5IiwgIkdpb3ZpbmF6emkiLCAiSGFtaWx0b24iLCAiTGF0aWZpIiwgIkxlY2xlcmMiLCAiTWF6ZXBpbiIsICJOb3JyaXMiLCAiT2NvbiIsICJQw6lyZXoiLCAiUsOkaWtrw7ZuZW4iLCAiUmljY2lhcmRvIiwgIlJ1c3NlbGwiLCAiU2FpbnoiLCAiU2NodW1hY2hlciIsICJTdHJvbGwiLCAiVHN1bm9kYSIsICJWZXJzdGFwcGVuIiwgIlZldHRlbCIpDQoNCnBpbG90b3NfMjAyMSA8LSAgZnVsbF9qb2luKGNhcnJlcmFzLCByZXN1bHRhZG9zLCBjKCJyYWNlSWQiID0gInJhY2VJZCIpICkgJT4lIA0KICBmdWxsX2pvaW4oLixwaWxvdG9zLCBjKCJkcml2ZXJJZCI9ImRyaXZlcklkIikpICU+JSANCiAgZmlsdGVyKHllYXI9PSIyMDIxIikgJT4lIA0KICBzZWxlY3QoZm9yZW5hbWUsc3VybmFtZSwgeWVhcikgJT4lIA0KICBkaXN0aW5jdChmb3JlbmFtZSxzdXJuYW1lKSAlPiUgDQogIG5hLm9taXQoKSAlPiUgDQogIGFycmFuZ2Uoc3VybmFtZSkgJT4lIA0KICBhZGRfY29sdW1uKG5vbWJyZXNfbm9ybWFsZXMpIA0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiN0ZW1wb3JhZGEgMjAyMSB0ZW1wbG9zDQoNCmNhcnJlcmFzXzIxIDwtIGZ1bGxfam9pbihjYXJyZXJhcyxjaXJjdWl0b3MsIGMoImNpcmN1aXRJZCIgPSAiY2lyY3VpdElkIikpICU+JQ0KICBmaWx0ZXIoeWVhcj09IjIwMjEiKSAlPiUNCiAgc2VsZWN0KHJvdW5kLCBuYW1lLngsIG5hbWUueSwgZGF0ZSwgbG9jYXRpb24sY291bnRyeSwgbGF0LCBsbmcsIGFsdCkgJT4lDQogIGFycmFuZ2Uocm91bmQpICU+JSANCiAgbXV0YXRlKHJvdW5kMiA9IHJvdW5kKSANCg0KY2FycmVyYXNfMjFfdjIgPC0gY2FycmVyYXNfMjFbLCBjKDEsIDQsIDEwLCAyLCAzLCA1LCA2LCA3LCA4LCA5KV0NCmNhcnJlcmFzXzIxX3YyIDwtIGNhcnJlcmFzXzIxX3YyJT4lICB1bml0ZSguICx2YXJpYWJsZXMsIGMoMSwgNSwgNyksIHNlcCA9ICI7ICIpDQoNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiNlbCBuYW5vIGNvbnRyYSB0b2Rvcw0KDQoNCmFsb3ZzYWxsIDwtIGZ1bGxfam9pbihwaWxvdG9zLCByZXN1bHRhZG9zLCBjICgiZHJpdmVySWQiID0gImRyaXZlcklkIikpICU+JSAgDQogIHNlbGVjdChkcml2ZXJSZWYsIHJlc3VsdElkLCByYWNlSWQsIGNvbnN0cnVjdG9ySWQsIHBvc2l0aW9uLCBwb2ludHMpICU+JSANCiAgZnVsbF9qb2luKC4sIGVzY3VkZXJpYXMsIGMgKCJjb25zdHJ1Y3RvcklkIiA9ICJjb25zdHJ1Y3RvcklkIikpICU+JSANCiAgc2VsZWN0KGRyaXZlclJlZiwgcmVzdWx0SWQsIHJhY2VJZCwgY29uc3RydWN0b3JJZCwgcG9zaXRpb24sIHBvc2l0aW9uLCBwb2ludHMsIG5hbWUpICU+JSANCiAgZnVsbF9qb2luKC4sIGNhcnJlcmFzLCBjICgicmFjZUlkIiA9ICJyYWNlSWQiKSkgJT4lIA0KICBzZWxlY3QoZHJpdmVyUmVmLCByZXN1bHRJZCwgcmFjZUlkLCBjb25zdHJ1Y3RvcklkLCBwb3NpdGlvbiwgcG9zaXRpb24sIHBvaW50cywgbmFtZS54LCB5ZWFyLCByb3VuZCkNCg0KI2Fsb192c19tYXJxdWVzIDwtIGFsb3ZzYWxsICU+JSBmaWx0ZXIoeWVhciA9PSAyMDAxLCBkcml2ZXJSZWYgJWluJSBjKCJhbG9uc28iLCAibWFycXVlcyIpLCByb3VuZCA8PSAxNCkNCg0KYWxvX3ZzX3RydWxsaSA8LSBhbG92c2FsbCAlPiUgZmlsdGVyKHllYXIgJWluJSBjKDIwMDMsIDIwMDQpLCBkcml2ZXJSZWYgJWluJSBjKCJhbG9uc28iLCAidHJ1bGxpIikpICU+JSBzbGljZSgxOjE1LCAxNzo2NykgJT4lIGdyb3VwX2J5KGRyaXZlclJlZiwgeWVhcikgJT4lIG11dGF0ZShwdW50b3NfYWN1bXVsYWRvcyA9IGN1bXN1bShwb2ludHMpKSAlPiUgdW5ncm91cCgpDQoNCmFsb192c19maXNpY2hlbGxhIDwtIGFsb3ZzYWxsICU+JSBmaWx0ZXIoeWVhciAlaW4lIGMoMjAwNSwgMjAwNiksIGRyaXZlclJlZiAlaW4lIGMoImFsb25zbyIsICJmaXNpY2hlbGxhIikpICAlPiUgZ3JvdXBfYnkoZHJpdmVyUmVmLCB5ZWFyKSAlPiUgbXV0YXRlKHB1bnRvc19hY3VtdWxhZG9zID0gY3Vtc3VtKHBvaW50cykpICU+JSB1bmdyb3VwKCkNCg0KYWxvX3ZzX2hhbWlsdG9uIDwtIGFsb3ZzYWxsICU+JSBmaWx0ZXIoeWVhciAlaW4lIGMoMjAwNykgLGRyaXZlclJlZiAlaW4lIGMoImFsb25zbyIsICJoYW1pbHRvbiIpKSAgJT4lIGdyb3VwX2J5KGRyaXZlclJlZiwgeWVhcikgJT4lIG11dGF0ZShwdW50b3NfYWN1bXVsYWRvcyA9IGN1bXN1bShwb2ludHMpKSAlPiUgdW5ncm91cCgpDQoNCmFsb192c19waXF1ZXQgPC0gYWxvdnNhbGwgJT4lIGZpbHRlcih5ZWFyICVpbiUgYygyMDA4LCAyMDA5KSwgZHJpdmVyUmVmICVpbiUgYygiYWxvbnNvIiwgInBpcXVldF9qciIpKSAlPiUgc2xpY2UoMToyOCwgMzY6NjMpICU+JSBncm91cF9ieShkcml2ZXJSZWYsIHllYXIpICU+JSBtdXRhdGUocHVudG9zX2FjdW11bGFkb3MgPSBjdW1zdW0ocG9pbnRzKSkgJT4lIHVuZ3JvdXAoKQ0KDQojYWxvX3ZzX2dyb3NqZWFuIDwtIGFsb3ZzYWxsICU+JSBmaWx0ZXIoeWVhciA9PSAyMDA5LCBkcml2ZXJSZWYgJWluJSBjKCJhbG9uc28iLCAiZ3Jvc2plYW4iKSwgcm91bmQgPj0gMTEpDQoNCmFsb192c19tYXNzYSA8LSBhbG92c2FsbCAlPiUgZmlsdGVyKHllYXIgJWluJSBjKDIwMTAsIDIwMTEsIDIwMTMpLCBkcml2ZXJSZWYgJWluJSBjKCJhbG9uc28iLCAibWFzc2EiKSkgJT4lIGdyb3VwX2J5KGRyaXZlclJlZiwgeWVhcikgJT4lIG11dGF0ZShwdW50b3NfYWN1bXVsYWRvcyA9IGN1bXN1bShwb2ludHMpKSAlPiUgdW5ncm91cCgpDQoNCmFsb192c19yYWlra29uZW4gPC0gYWxvdnNhbGwgJT4lIGZpbHRlcih5ZWFyID09IDIwMTQsIGRyaXZlclJlZiAlaW4lIGMoImFsb25zbyIsICJyYWlra29uZW4iKSkgJT4lIGdyb3VwX2J5KGRyaXZlclJlZiwgeWVhcikgJT4lIG11dGF0ZShwdW50b3NfYWN1bXVsYWRvcyA9IGN1bXN1bShwb2ludHMpKSAlPiUgdW5ncm91cCgpDQoNCmFsb192c19idXR0b24gPC0gYWxvdnNhbGwgJT4lIGZpbHRlcih5ZWFyICVpbiUgYygyMDE1LCAyMDE2KSwgZHJpdmVyUmVmICVpbiUgYygiYWxvbnNvIiwgImJ1dHRvbiIpKSAlPiUgZ3JvdXBfYnkoZHJpdmVyUmVmLCB5ZWFyKSAlPiUgbXV0YXRlKHB1bnRvc19hY3VtdWxhZG9zID0gY3Vtc3VtKHBvaW50cykpICU+JSB1bmdyb3VwKCkNCg0KYWxvX3ZzX3ZhbmRvb3JuZSA8LSBhbG92c2FsbCAlPiUgZmlsdGVyKHllYXIgJWluJSBjKDIwMTcsIDIwMTgpLCBkcml2ZXJSZWYgJWluJSBjKCJhbG9uc28iLCAidmFuZG9vcm5lIikpICU+JSBzbGljZSgxOjQ1LCA0Nzo4MSkgJT4lIGdyb3VwX2J5KGRyaXZlclJlZiwgeWVhcikgJT4lIG11dGF0ZShwdW50b3NfYWN1bXVsYWRvcyA9IGN1bXN1bShwb2ludHMpKSU+JSB1bmdyb3VwKCkgDQoNCmFsb192c19vY29uIDwtIGFsb3ZzYWxsICU+JSBmaWx0ZXIoeWVhciA9PSAyMDIxLCBkcml2ZXJSZWYgJWluJSBjKCJhbG9uc28iLCAib2NvbiIpKSAlPiUgZ3JvdXBfYnkoZHJpdmVyUmVmLCB5ZWFyKSAlPiUgbXV0YXRlKHB1bnRvc19hY3VtdWxhZG9zID0gY3Vtc3VtKHBvaW50cykpICU+JSB1bmdyb3VwKCkNCg0KQUxPX1ZTX0FMTCA8LSBmdWxsX2pvaW4oYWxvX3ZzX3RydWxsaSwgYWxvX3ZzX2Zpc2ljaGVsbGEsIGMoImRyaXZlclJlZiI9ICJkcml2ZXJSZWYiLCAicmVzdWx0SWQiID0gInJlc3VsdElkIiwgInJhY2VJZCIgPSAicmFjZUlkIiwgImNvbnN0cnVjdG9ySWQiID0gImNvbnN0cnVjdG9ySWQiLCAicG9zaXRpb24iID0gInBvc2l0aW9uIiwgInBvaW50cyIgPSAicG9pbnRzIiwgIm5hbWUueCIgPSAibmFtZS54IiwgInllYXIiID0gInllYXIiLCAicm91bmQiID0gInJvdW5kIiAsICJwdW50b3NfYWN1bXVsYWRvcyIgPSAicHVudG9zX2FjdW11bGFkb3MiKSkgJT4lIA0KICBmdWxsX2pvaW4oLiwgYWxvX3ZzX2hhbWlsdG9uLCBjKCJkcml2ZXJSZWYiPSAiZHJpdmVyUmVmIiwgInJlc3VsdElkIiA9ICJyZXN1bHRJZCIsICJyYWNlSWQiID0gInJhY2VJZCIsICJjb25zdHJ1Y3RvcklkIiA9ICJjb25zdHJ1Y3RvcklkIiwgInBvc2l0aW9uIiA9ICJwb3NpdGlvbiIsICJwb2ludHMiID0gInBvaW50cyIsICJuYW1lLngiID0gIm5hbWUueCIsICJ5ZWFyIiA9ICJ5ZWFyIiwgInJvdW5kIiA9ICJyb3VuZCIsICJwdW50b3NfYWN1bXVsYWRvcyIgPSAicHVudG9zX2FjdW11bGFkb3MiKSkgJT4lIA0KICBmdWxsX2pvaW4oLiwgYWxvX3ZzX3BpcXVldCwgYygiZHJpdmVyUmVmIj0gImRyaXZlclJlZiIsICJyZXN1bHRJZCIgPSAicmVzdWx0SWQiLCAicmFjZUlkIiA9ICJyYWNlSWQiLCAiY29uc3RydWN0b3JJZCIgPSAiY29uc3RydWN0b3JJZCIsICJwb3NpdGlvbiIgPSAicG9zaXRpb24iLCAicG9pbnRzIiA9ICJwb2ludHMiLCAibmFtZS54IiA9ICJuYW1lLngiLCAieWVhciIgPSAieWVhciIsICJyb3VuZCIgPSAicm91bmQiLCAicHVudG9zX2FjdW11bGFkb3MiID0gInB1bnRvc19hY3VtdWxhZG9zIikpICU+JSANCiAgZnVsbF9qb2luKC4sIGFsb192c19tYXNzYSwgYygiZHJpdmVyUmVmIj0gImRyaXZlclJlZiIsICJyZXN1bHRJZCIgPSAicmVzdWx0SWQiLCAicmFjZUlkIiA9ICJyYWNlSWQiLCAiY29uc3RydWN0b3JJZCIgPSAiY29uc3RydWN0b3JJZCIsICJwb3NpdGlvbiIgPSAicG9zaXRpb24iLCAicG9pbnRzIiA9ICJwb2ludHMiLCAibmFtZS54IiA9ICJuYW1lLngiLCAieWVhciIgPSAieWVhciIsICJyb3VuZCIgPSAicm91bmQiLCAicHVudG9zX2FjdW11bGFkb3MiID0gInB1bnRvc19hY3VtdWxhZG9zIikpICAlPiUgDQogIGZ1bGxfam9pbiguLCBhbG9fdnNfcmFpa2tvbmVuLCBjKCJkcml2ZXJSZWYiPSAiZHJpdmVyUmVmIiwgInJlc3VsdElkIiA9ICJyZXN1bHRJZCIsICJyYWNlSWQiID0gInJhY2VJZCIsICJjb25zdHJ1Y3RvcklkIiA9ICJjb25zdHJ1Y3RvcklkIiwgInBvc2l0aW9uIiA9ICJwb3NpdGlvbiIsICJwb2ludHMiID0gInBvaW50cyIsICJuYW1lLngiID0gIm5hbWUueCIsICJ5ZWFyIiA9ICJ5ZWFyIiwgInJvdW5kIiA9ICJyb3VuZCIsICJwdW50b3NfYWN1bXVsYWRvcyIgPSAicHVudG9zX2FjdW11bGFkb3MiKSkgJT4lIA0KICBmdWxsX2pvaW4oLiwgYWxvX3ZzX2J1dHRvbiwgYygiZHJpdmVyUmVmIj0gImRyaXZlclJlZiIsICJyZXN1bHRJZCIgPSAicmVzdWx0SWQiLCAicmFjZUlkIiA9ICJyYWNlSWQiLCAiY29uc3RydWN0b3JJZCIgPSAiY29uc3RydWN0b3JJZCIsICJwb3NpdGlvbiIgPSAicG9zaXRpb24iLCAicG9pbnRzIiA9ICJwb2ludHMiLCAibmFtZS54IiA9ICJuYW1lLngiLCAieWVhciIgPSAieWVhciIsICJyb3VuZCIgPSAicm91bmQiLCAicHVudG9zX2FjdW11bGFkb3MiID0gInB1bnRvc19hY3VtdWxhZG9zIikpICU+JSANCiAgZnVsbF9qb2luKC4sIGFsb192c192YW5kb29ybmUsIGMoImRyaXZlclJlZiI9ICJkcml2ZXJSZWYiLCAicmVzdWx0SWQiID0gInJlc3VsdElkIiwgInJhY2VJZCIgPSAicmFjZUlkIiwgImNvbnN0cnVjdG9ySWQiID0gImNvbnN0cnVjdG9ySWQiLCAicG9zaXRpb24iID0gInBvc2l0aW9uIiwgInBvaW50cyIgPSAicG9pbnRzIiwgIm5hbWUueCIgPSAibmFtZS54IiwgInllYXIiID0gInllYXIiLCAicm91bmQiID0gInJvdW5kIiwgInB1bnRvc19hY3VtdWxhZG9zIiA9ICJwdW50b3NfYWN1bXVsYWRvcyIpKSAlPiUgDQogIGZ1bGxfam9pbiguLCBhbG9fdnNfb2NvbiwgYygiZHJpdmVyUmVmIj0gImRyaXZlclJlZiIsICJyZXN1bHRJZCIgPSAicmVzdWx0SWQiLCAicmFjZUlkIiA9ICJyYWNlSWQiLCAiY29uc3RydWN0b3JJZCIgPSAiY29uc3RydWN0b3JJZCIsICJwb3NpdGlvbiIgPSAicG9zaXRpb24iLCAicG9pbnRzIiA9ICJwb2ludHMiLCAibmFtZS54IiA9ICJuYW1lLngiLCAieWVhciIgPSAieWVhciIsICJyb3VuZCIgPSAicm91bmQiLCAicHVudG9zX2FjdW11bGFkb3MiID0gInB1bnRvc19hY3VtdWxhZG9zIikpDQoNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KI2VsIG5hbm8gY29udHJhIGhhbWlsdG9uDQpmb3Rvc19BTE9fdnNfSEFNIDwtIGMoIi4vaW1hZ2VuZXMvcGlsb3Rvcy9hbG9uc28ucG5nIiwgIi4vaW1hZ2VuZXMvcGlsb3Rvcy9oYW1pbHRvbi5wbmciKQ0KZm90b3NfZXNwX2luZyA8LSBjKCIuL2ltYWdlbmVzL3BhaXNlcy9lc3BhbnlhLnBuZyIsICIuL2ltYWdlbmVzL3BhaXNlcy91ay5wbmciKQ0Kbl9jYXJyZXJhc19hbG9faGFtIDwtIG5fY2FycmVyYXNfbm9tICU+JSBmaWx0ZXIoZHJpdmVyUmVmICVpbiUgYygiYWxvbnNvIiwgImhhbWlsdG9uIikpDQoNCm5fdmljdG9yaWFzX2Fsb19oYW0gPC0gdmljdG9yaWFzX2Nvbl9ub21icmUgJT4lIGZpbHRlcihkcml2ZXJSZWYgJWluJSBjKCJhbG9uc28iLCAiaGFtaWx0b24iKSkNCg0KYWxvX3ZzX2hhbSA8LSBmdWxsX2pvaW4obl9jYXJyZXJhc19hbG9faGFtLCBuX3ZpY3Rvcmlhc19hbG9faGFtLCBjKCJkcml2ZXJSZWYiPSAiZHJpdmVyUmVmIikpICU+JSBzZWxlY3QoIGRyaXZlclJlZiwgbnVtZXJvX2NhcnJlcmFzLCBuX3ZpY3RvcmlhcykgJT4lIGFkZF9jb2x1bW4oZm90b3NfZXNwX2luZywgZm90b3NfQUxPX3ZzX0hBTSkgDQpgYGANCg0KDQojIDMuIFRoZSBwbGFuDQoNCiMjIDMuMSBVbiBwYXNlbyBwb3IgbGEgaGlzdG9yaWEgDQoNCkVsIG5hY2ltaWVudG8gZGUgbGEgRsOzcm11bGEgMSBzZSByZW1vbnRhIGEgMTk1MCwgZG9uZGUgbGEgRklBLCBGZWRlcmFjacOzbiBJbnRlcm5hY2lvbmFsIGRlbCBBdXRvbcOzdmlsLCBkZWNpZGnDsyB1bmlyIHZhcmlvcyBncmFuZGVzIHByZW1pb3MgZGUgZGlmZXJlbnRlcyBwYcOtc2VzLCBwYXJhIGNyZWFyIGVsIGNhbXBlb25hdG8gbXVuZGlhbCBkZSBwaWxvdG9zLiBFbCBwcmltZXIgZ3JhbiBwcmVtaW8gc2UgY2VsZWJyw7MgZW4gZWwgY2lyY3VpdG8gZGUgU2lsdmVyc3RvbmUsIGVsIDEzIGRlIG1heW8gZGUgMTk1MC4gIERlc2RlIGVudG9uY2VzLCBMYSBGw7NybXVsYSAxIGhhIGlkbyBldm9sdWNpb25hbmRvLCB0YW50byBhIG5pdmVsIGRlIGNvY2hlcywgY2lyY3VpdG9zLCBvIGxvZ29zLCBwYXJhIGFjYWJhciBzaWVuZG8gZWwgZXNwZWN0w6FjdWxvIHF1ZSBlcyBlbiBsYSBhY3R1YWxpZGFkLg0KDQojIyMgQ29jaGVzDQoNCkVsIGF1dG9tw7N2aWwgcHVlZGUgc2VyIGVsIGVsZW1lbnRvIHF1ZSBtYXlvcmVzIGNhbWJpb3MgaGEgZXhwZXJpbWV0bmFkbyBjb24gZWwgcGFzbyBkZWwgdGllbXBvLiBFbiBsb3MgYcOxb3MgNTAsIGxhcyBlc2N1ZGVyaWFzIG3DoXMgZGVzdGFjYWJsZXMgZXJhbiBsb3MgcHJvcGlvcyBmYWJyaWNhbnRlcyBkZSB2ZWjDrWN1bG9zLCBwb3IgZWplbXBsbyBNYXNlcmF0aSBvIEFsZmEgUm9tZW8uIExvcyBjb2NoZXMgZW4gZXN0YSBkw6ljYWRhIHNlIGNhcmFjdGVyaXphYmFuIHBvciB0ZW5lciB1biBtb3RvciBmcm9udGFsLCBhIGRpZmVyZW5jaWEgZGUgbG8gcXVlIHBhc2Fyw61hIGVuIGHDsW9zIHBvc3RlcmlvcmVzLiAgICANCg0KQSBwYXJ0aXIgZGUgbGEgZMOpY2FkYSBkZSBsb3MgNjAsIHNlIGNvbWVuemFyb24gYSB1dGlsaXphciB2ZWjDrWN1bG9zIGNvbiBtb3RvciBjZW50cmFsLCBzdXBvbmllbmRvIHVuYSBpbXBvcnRhbnRlIG1lam9yYSBlbiBlbCBkZXNlbXBlw7FvIGRlIGxvcyBjb2NoZXMuIEFkZW3DoXMsIHNlIGRpbyBwZXNvIGEgb3Ryb3MgYXNwZWN0b3MsIGNvbW8gbGEgY29tcG9zaWNpw7NuIGRlbCBjaGFzaXMsIHNpZW5kbyBsYSBlc2N1ZGVyw61hIGxvdHVzIHBpb25lcmEgZW4gaW50cm9kdWNpciBsb3MgY2hhc2lzIG1vbm9jYXNjbyBkZSBhbHVtaW5pby4gICANCg0KRW4gbG9zIDcwLCBsYSBhZXJvZGluw6FtaWNhIHBhc8OzIGEgdGVuZXIgdW4gcGFwZWwgZnVuZGFtZW50YWwsIGludHJvZHVjaWVuZG9zZSBlbCBlZmVjdG8gc3VlbG8sIHEgcGVybWl0w61hIHJvZGFyIGEgbWF5b3IgdmVsb2NpZGFkIGVuIGxhcyBjdXJ2YXMuIEVudHJlIDE5ODAgeSAxOTkwIGRlc3RhY2FuIGxhcyBheXVkYXMgZWxlY3Ryw7NuaWNhcywgY29tbyBwb3IgZWplbXBsbyBsYSBzdXNwZW5zacOzbiBhY3RpdmEsIGVsIGNhbWJpbyBkZSBtYXJjaGFzIHNlbWktYXV0b23DoXRpY28sIG8gZWwgY29udHJvbCBkZSB0cmFjY2nDs24uICAgIA0KDQpEZXNkZSBlbnRvbmNlcywgaGFzdGEgbGEgYWN0dWFsaWRhZCwgbG9zIGNhbW1iaW9zIGVuIGxvcyBjb2NoZXMgbm8gaGFuIHNpZG8gdGFuIHJlbGV2YW50ZXMsIHByb2R1Y2llbmRvc2UgdW4gZXF1aWxpYnJpbyBlbiBsYXMgbWVqb3JhcyBkZSBsYXMgZGlzdGludGFzIHBhcnRlcyBkZWwgdmVow61jdWxvOiBhZXJvZGluw6FtaWNhLCBjaGFzaXMgeSBtb3Rvci4NCg0KYGBge3J9DQoNCmNvY2hlMTk1MCA8LSBpbWFnZV9yZWFkKCIuL2ltYWdlbmVzL2NvY2hlcy8xOTUwLmpwZyIpICU+JSBpbWFnZV9zY2FsZSguLCAiNTAwIikgJT4lICBpbWFnZV9hbm5vdGF0ZSguLCAiMTk1MCIsIHNpemUgPSA0MCwgZ3Jhdml0eSA9ICJzb3V0aHdlc3QiLCBjb2xvciA9ICJ3aGl0ZSIpDQpjb2NoZTE5NjAgPC0gaW1hZ2VfcmVhZCgiLi9pbWFnZW5lcy9jb2NoZXMvMTk2MC5qcGciKSAlPiUgaW1hZ2Vfc2NhbGUoLiwgIjUwMCIpJT4lICBpbWFnZV9hbm5vdGF0ZSguLCAiMTk2MCIsIHNpemUgPSA0MCwgZ3Jhdml0eSA9ICJzb3V0aHdlc3QiLCBjb2xvciA9ICJ3aGl0ZSIpDQpjb2NoZTE5NzAgPC0gaW1hZ2VfcmVhZCgiLi9pbWFnZW5lcy9jb2NoZXMvMTk3MC5qcGciKSAlPiUgaW1hZ2Vfc2NhbGUoLiwgIjUwMCIpJT4lICBpbWFnZV9hbm5vdGF0ZSguLCAiMTk3MCIsIHNpemUgPSA0MCwgZ3Jhdml0eSA9ICJzb3V0aHdlc3QiLCBjb2xvciA9ICJ3aGl0ZSIpDQpjb2NoZTE5ODAgPC0gaW1hZ2VfcmVhZCgiLi9pbWFnZW5lcy9jb2NoZXMvMTk4MC5qcGciKSAlPiUgaW1hZ2Vfc2NhbGUoLiwgIjUwMCIpJT4lICBpbWFnZV9hbm5vdGF0ZSguLCAiMTk4MCIsIHNpemUgPSA0MCwgZ3Jhdml0eSA9ICJzb3V0aHdlc3QiLCBjb2xvciA9ICJ3aGl0ZSIpDQpjb2NoZTE5OTAgPC0gaW1hZ2VfcmVhZCgiLi9pbWFnZW5lcy9jb2NoZXMvMTk5MC5qcGciKSAlPiUgaW1hZ2Vfc2NhbGUoLiwgIjUwMCIpJT4lICBpbWFnZV9hbm5vdGF0ZSguLCAiMTk5MCIsIHNpemUgPSA0MCwgZ3Jhdml0eSA9ICJzb3V0aHdlc3QiLCBjb2xvciA9ICJ3aGl0ZSIpDQpjb2NoZTIwMDUgPC0gaW1hZ2VfcmVhZCgiLi9pbWFnZW5lcy9jb2NoZXMvMjAwNS5qcGciKSAlPiUgaW1hZ2Vfc2NhbGUoLiwgIjUwMCIpJT4lICBpbWFnZV9hbm5vdGF0ZSguLCAiMjAwNSIsIHNpemUgPSA0MCwgZ3Jhdml0eSA9ICJzb3V0aHdlc3QiLCBjb2xvciA9ICJ3aGl0ZSIpDQpjb2NoZTIwMjAgPC0gaW1hZ2VfcmVhZCgiLi9pbWFnZW5lcy9jb2NoZXMvMjAyMC5qcGciKSAlPiUgaW1hZ2Vfc2NhbGUoLiwgIjUwMCIpJT4lICBpbWFnZV9hbm5vdGF0ZSguLCAiMjAyMCIsIHNpemUgPSA0MCwgZ3Jhdml0eSA9ICJzb3V0aHdlc3QiLCBjb2xvciA9ICJ3aGl0ZSIpDQpjb2NoZXMgPC0gYyhjb2NoZTE5NTAsIGNvY2hlMTk2MCwgY29jaGUxOTcwLCBjb2NoZTE5ODAsIGNvY2hlMTk5MCwgY29jaGUyMDA1LCBjb2NoZTIwMjApDQoNCmltYWdlX2FuaW1hdGUoaW1hZ2Vfc2NhbGUoY29jaGVzKSwgZnBzID0gMC41KQ0KYGBgDQoNCiMjIyBMb2dvcyAgey50YWJzZXR9DQoNCiMjIyMgTG9nbyBkZSAxOTg1IGEgMTk4Ng0KDQpBdW5xdWUgbm8gdGFuIGVzcGVjdGFjdWxhciwgdGFtYmnDqW4gc2UgaGEgcHJvZHVjaWRvIHVhIGV2b2x1Y2nDs24gZGUgbGEgZXN0w6l0aWNhIGRlbCBsb2dvLCBwYXNhbmRvIGRlIHVuYSBpbWFnZW4gbcOhcyBjYXJnYWRhLCBlbiBsYSBxdWUgYXBhcmVjZSBoYXN0YSBlbCBzw61tYm9sbyBkZSBsYSBGSUEsIGFsIGxvZ28gYWN0dWFsLCBjb21wdWVzdG8gcG9yIGxhIEYgeSBlbCAxLg0KDQo8Y2VudGVyPg0KIVtMb2dvIGRlIDE5NTAgYSAxOTg2XSguL2ltYWdlbmVzL2xvZ29zLzE5ODUtMTk4Ni5wbmcpe3dpZHRoPTQwMCBoZWlnaHQ9NzB9DQo8L2NlbnRlcj4NCg0KDQojIyMjIExvZ28gZGUgMTk4NyBhIDE5OTMNCjxjZW50ZXI+DQohW0xvZ28gZGUgMTk4NyBhIDE5OTNdKC4vaW1hZ2VuZXMvbG9nb3MvMTk4Ny0xOTkzLmpwZyl7d2lkdGg9MjUwIGhlaWdodD0zMDB9DQo8L2NlbnRlcj4NCg0KDQojIyMjIExvZ28gZGUgMTk5NCBhIDIwMTcNCjxjZW50ZXI+DQohW0xvZ28gZGUgMTk5NCBhIDIwMTddKC4vaW1hZ2VuZXMvbG9nb3MvMTk5NC0yMDE3LnBuZyl7d2lkdGg9NDUwIGhlaWdodD0zMDB9DQo8L2NlbnRlcj4NCg0KDQojIyMjIExvZ28gQWN0dWFsDQo8Y2VudGVyPg0KIVtMT0dPIGRlc2RlIDIwMTggaGFzdGEgbGEgYWN0dWFsaWRhZF0oLi9pbWFnZW5lcy9sb2dvcy8yMDE4LS5wbmcpe3dpZHRoPTQwMCBoZWlnaHQ9MzAwfQ0KPC9jZW50ZXI+ICANCg0KDQojIyMgQ2Fww610dWxvIG9zY3VybyBkZWwgZGVwb3J0ZQ0KDQpIYXkgcXVlIHNlciBjb25zY2llbnRlcyBxdWUsIGRlIGlndWFsIG1hbmVyYSBxdWUgbGEgRm9ybXVsYSAxIGVzIGVzcGVjdGFjdWxhciwgc3VzIHBpbG90b3Mgc2UgZXhwb25lbiBhIHVuIGdyYW4gcmllc2dvLiBQcnVlYmEgZGUgZWxsbyBlcywgZWwgZ3LDoWZpY28gbW9zdHJhZG8gYSBjb250aW51YWNpw7NuLCBlbiBlbCBjdWFsIHNlIHJlZmxlamEgdG9kYXMgbGFzIG11ZXJ0ZXMgZGUgcGlsb3RvcyBwcm9kdWNpZGFzIGVuIGxhIEYxLiBFbCAgdG90YWwgZXMgZGUgNDIsIHNpZW5kbyBsYSBwZW9yIGRlY2FkYSBsb3MgYcOxb3MgNTAsIHByb2R1Y2llbmRvc2UgMTUgZmFsbGVjaW1pZW50b3MuIEVuIGRpY2hvIHBlcmlvZG8sIGRlc3RhY2Egc29icmUgbG9zIGRlbcOhcyBjaXJjdWl0byBsYXMgNTAwIG1pbGxhcyBkZSBJbmRpYW7DoXBvbGlzLCBsYSBjdWFsIGVzdGFiYSBkdXJhbnRlIGxvcyBwcmltZXJvcyBhw7FvcyBkZSBsYSBGMSBkZW50cm8gZGUgbG9zIGNpcmN1aXRvcyBkZWwgY2FtcGVvbmF0by4gUG9yIG90cm8gbGFkbywgY2FiZSBkZXN0YWNhciBsYXMgbXVlcnRlcyBkZSBSb2xhbmQgUmF0emVuYmVyZ2VyIHkgQXlydG9uIFNlbm5hLCBlbiBlbCBncmFuIHByZW1pbyBkZSBTYW4gTWFyaW5vIGRlIDE5OTQuIFN1cHVzbyB1biBwdW50byBkZSBpbmZsZXhpw7NuIGVuIGxhIHNlZ3VyaWRhZCBkZSBsYXMgY2FycmVyYXMsIGRlYmlkbyBhIHF1ZSBkZXNkZSAxOTYwLCBubyBzZSBoYWLDrWFuIHByb2R1Y2lkbyBkb3MgbXVlcnRlcyBlbiB1biBtaXNtbyBmaW4gZGUgc2VtYW5hLCBzdW1hZG8gYSAgcXVlIEF5cnRvbiBTZW5uYSBlcmEgdW5hIGRlIGxhcyBlc3RyZWxsYXMgZGUgbGEgRjEgZW4gZXNlIG1vbWVudG8uIERlc2RlIGVzYSBmZWNoYSBubyBzZSB2b2x2aWVyb24gYSBwcm9kdWNpciBtdWVydGVzIGRlIHBpbG90b3MgaGFzdGEgZWwgZ3JhbiBwcmVtaW8gZGUgSmFww7NuIGRlIDIwMTQsIGZhbGxlY2llbmRvIEp1bGVzIEJpYW5jaGksIHNpZW5kbyBsYSDDumx0aW1hIG11ZXJ0ZS4gICAgICAgIA0KDQpTaW4gZW1iYXJnbywgbGEgdGVuZGVuY2lhIGhhIHNpZG8gY2xhcmFtZW50ZSBuZWdhdGl2YSwgZGViaWRvIGEgbGFzIGRpZmVyZW50ZXMgbWVkaWRhcyBkZSBzZWd1cmlkYWQgcXVlIHNlIGhhbiBpZG8gaW5jb3Jwb3JhbmRvLkFsZ3VuYXMgZGUgbGFzIG1lam9yYXMgbcOhcyBkZXN0YWNhZGFzIGhhbiBzaWRvLCBsYXMgcHJvdGVjaW9uZXMgeSBncmF2YSBlbiBsb3MgY2lyY3VpdG9zLCBsb3MgbW9ub3MgaWduw61mdWdvcyBvIGxhIHJlZ2xhbWVudGFjacOzbiBlbiBlbCBkaXNlw7FvIGRlbCBjYXNjby5MYSDDumx0aW1hIGludHJvZHVjY2nDs24gaGEgc2lkbyBlbCBoYWxvLCBjZW50cmFkbyBlbiBldml0YXIgZ29scGVzIG8gYXBsYXN0YW1pZW50b3MgZGUgbGEgY2FiZXphIGRlbCBwaWxvdG8uIEEgcGVzYXIgZGUgYWxndW5hcyBjcsOtdGljYXMsIHN1IHBhcGVsIHlhIGhhIHNpZG8gZnVuZGFtZW50YWwsIHBvciBlamVtcGxvIHBhcmEgZXZpdGFyIG1heW9yZXMgZGHDsW9zIGVuIGVsIGFjY2lkZW50ZSBxdWUgc3VmcmnDsyBlbCBwaWxvdG8gUm9tYWluIEdyb3NqZWFuIGVuIGVsIGdyYW4gcHJlbWlvIGRlIEJhaHJlaW4gZW4gMjAyMC4NCg0KYGBge3IsIGV2YWwgPSBUUlVFLCBlY2hvID0gVFJVRX0NCmdnX211ZXJ0ZXMgPC0gZ2dwbG90KG11ZXJ0ZXNmMV9maW5hbCwgYWVzKHggPSBmZWNoYV9tdWVydGUsIHkgPSBtdWVydGVzeGFueW8gKSkgKyAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAid2hpdGUiKSArIGdlb21fc21vb3RoKGNvbG91ciA9ICJjeWFuIiwgc2UgPSBGQUxTRSkgKyBsYWJzKHggPSAiQcOxbyIgLCB5ID0gIk7Dum1lcm8gZGUgbXVlcnRlcyIpICArIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAid2hpdGUiKSwNCiAgICBheGlzLnRpY2tzID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJ3aGl0ZSIpLA0KICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXkxMyIpLA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXkxMyIpLA0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3VyID0gIndoaXRlIiksDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJ3aGl0ZSIpLA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3VyID0gIndoaXRlIiksDQogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIsDQogICAgICAgIGNvbG91ciA9ICJ3aGl0ZSIpLCBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiKSkgK2xhYnMoY29sb3VyID0gIndoaXRlIikgKyB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmF5MzgiLA0KICAgIGxpbmV0eXBlID0gImRvdHRlZCIpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9IE5BKSwNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyNSwNCiAgICAgICAgaGp1c3QgPSAwLjUpKSArbGFicyh0aXRsZSA9ICJBY2NpZGVudGVzIG1vcnRhbGVzIHBvciBhw7FvIikgKyBnZW9tX3RleHQoZGF0YSA9IGRhdGEuZnJhbWUoeCA9IDIwMDQuMTA1MjI2NDI4NzUsIHkgPSAwLjIzNzQ1MDUxNjk0MjI0MSwgDQogICAgbGFiZWwgPSAiVGVuZGVuY2lhIG5lZ2F0aXZhIiksIG1hcHBpbmcgPSBhZXMoeCA9IHgsIHkgPSB5LCANCiAgICBsYWJlbCA9IGxhYmVsKSwgY29sb3VyID0gImN5YW4iLCBpbmhlcml0LmFlcyA9IEZBTFNFLCBzaXplID0gMykNCg0KZ2dwbG90bHkoZ2dfbXVlcnRlcykNCg0KDQpgYGANCg0KDQojIyAzLjIgTG8gbcOhcyBkZXN0YWNhZG8gDQoNCkNvbW8gc2UgaW5kaWNhIGFsIGluaWNpbyBkZWwgdHJhYmFqbywgbGEgRjEgZXMgdW4gZGVwb3J0ZSBlbiBlbCBxdWUgbG9zIGRhdG9zIHRpZW5lbiB1bmEgZ3JhbiBpbXBvcnRhbmNpYS4gUGVybyBkaWNoYSBpbmZvcm1hY2nDs24gbm8gc29sbyBlcyDDunRpbCBwYXJhIGxvcyBwaWxvdG9zL2VzY3VkZXJpYXMsIHNpbm8gcXVlIHRhbWJpw6luIHBlcm1pdGUgcmVhbGl6YXIgb3RybyB0aXBvIGRlIGFuw6FsaXNpcywgcG9yIGVqZW1wbG8sIGRlc2RlIGVsIHB1bnRvIGRlIGxhIEYxIGNvbW8gbmVnb2NpbywgZXN0dWRpYW5kbyBsYXMgYXVkaWVuY2lhcywgZWwgZGluZXJvIG90ZW5pZG8gcG9yIHB1YmxpY2lkYWQsIG8gbG9zIGFzaXN0ZW50ZXMgYSBjYWRhIGdyYW4gcHJlbWlvIGNlbGVicmFkby4gUG9yIG90cm8gbGFkbywgcHVlZGUgc2VydmlyIHBhcmEgbG9zIGFmaWNpb25hZG9zIGEgbGEgaG9yYSBkZSBjb21wYXJhciBzdXMgcGlsb3RvcyBmYXZvcml0b3MsIG8gcXVlIGVzY3VkZXLDrWEgZXMgbGEgbWVqb3IuDQoNCg0KIyMjIEF1ZGVuY2lhcw0KDQpFbCBuw7ptZXJvIGRlIHBlcnNvbmFzIHF1ZSBzaWd1ZW4gbGEgRm9ybXVsYSAxIGVuIG51ZXN0cm8gcGHDrXMgaGEgZGVwZW5kaWRvIGVuIGdyYW4gbWVkaWRhIGRlIGxhIGZpZ3VyYSBkZSBGZXJuYW5kbyBBbG9uc28uIFBydWViYSBkZSBlbGxvIGVzIGVsIGdyw6FmaWNvIG1vc3RyYWRvIGFiYWpvLCBlbCBjdWFsIHJlZmxlamEgbGFzIGF1ZGllbmNpYXMgZGUgRjEgZW4gRXNwYcOxYSBlbnRyZSAyMDA0IHkgMjAyMC4gIA0KDQpDdWFudG8gbcOhcyBjcmVjw61hbiBsYXMgdmljdG9yaWFzIGRlIEFsb25zbywgZ2FuYW5kbyBlbCBtdW5kaWFsIGRlIHBpbG90b3MgZW4gMjAwNSB5IDIwMDYsIG3DoXMgcGVyc29uYXMgc2VndcOtYW4gbGEgZm9ybXVsYSAxLCBsbGVnYW5kbyBhIHN1IHBpY28gZW4gMjAwNywgZG9uZGUgc2UgcHJvZHVqbyB1bmEgdGVtcG9yYWRhIGxsZW5hIGRlIHBvbMOpbWljYXMgZW50cmUgQWxvbnNvLCBIYW1pbHRvbiB5IGVsIGVxdWlwbyBNY0xhcmVuLCBhbGNhbnphbmRvIGNpZnJhcyBkZSA0LDUgbWlsbG9uZXMgZGUgZXNwZWN0YWRvcmVzLiBTZSBwcm9kdWpvIHVuIHBlcXVlw7FvIGJhasOzbiBsb3MgZG9zIGHDsW9zIHBvc3RlcmlvcmVzLCB5YSBxdWUgbGEgdnVlbHRhIGRlIEFsb25zbyBhIHJlbmF1bHQgbm8gZnVlIG11eSBleGlzdG9zYS4gTGFzIGF1ZGllbmNpYXMgc2Ugdm9sdmllcm9uIGEgZGlzcGFyYW4gY29uIGxhIGxsZWdhZGEgZGVsIGFzdHVyaWFubyBhIEZlcnJyYXJpLCBwZXJvIGRlc3B1ZXMgZGUgZG9zIHN1YmNhbXBlb25hdG9zLCBsb3MgZXNwZWN0YWRvcmVzIGZ1ZXJvbiBkZWNheWVuZG8sIHkgbcOhcyBjb24gbGFzIGRlc2FzdHJvc2FzIHRlbXBvcmFkYXMgcXVlIHR1dm8gZW4gTWNMYXJlbiBlbnRyZSAyMDE1IHkgMjAxOC4gU2kgYSBlc3RvIGxlIHN1bWFtb3MgcXVlIGEgcGFydGlyIGRlIDIwMTYgbGEgRjEgc29sbyBzZSBwb2TDrWEgc2VndWlyIGEgdHJhdsOpcyBkZSBwbGF0YWZvcm1hcyBkZSBwYWdvIGVuIEVzcGHDsWEsIG5vcyBlY29udHJhbW9zIGNvbiBjaWZyYXMgYmFqaXNpbWFzIGVuIGxhIMO6bHRpbWEgZXRhcGEuIA0KDQpgYGB7ciwgZXZhbCA9IFRSVUUsIGVjaG8gPSBUUlVFfQ0KYXVkaWVuY2lhcyA8LSByaW86OmltcG9ydChmaWxlID0gIi4vZGF0b3MvYXVkaWVuY2lhc0YxLmNzdiIpDQoNCg0KZ2dfYXVkaWVuY2lhcyA8LSBnZ3Bsb3QoYXVkaWVuY2lhcywgYWVzKHg9eWVhciwgeT0gbnVtZXJvX2VzcGVjdGFkb3JlcykpICsNCiAgZ2VvbV9hcmVhKCkgKw0KICBnZW9tX3BvaW50KCBzaXplPTEuNSwgY29sb3I9ImN5YW4iLCBmaWxsPWFscGhhKCJjeWFuIiwgOCksIHNoYXBlPTIxLCBzdHJva2U9MikgKyAgDQogIGdlb21fbGluZShjb2xvcj0iIzY5YjNhMiIsIHNpemU9MSkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoDQogICAgYnJlYWtzID0gc2VxKDIwMDQsIDIwMjAsIDEpLA0KICAgIGxpbWl0cyA9IGMoMjAwMywgMjAyMSkpICsgbGFicyh4ID0gIkHDsW8iLCB5ID0gIk51bWVybyBkZSBlc3BlY3RhZG9yZXMiICkgICsgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIpLA0KICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIpKSArIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAid2hpdGUiKSwNCiAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmF5MjAiKSwNCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmF5MjAiKSwNCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gIndoaXRlIiksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3VyID0gIndoaXRlIiksDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAid2hpdGUiLA0KICAgICAgICBoanVzdCA9IDAuNSkpICtsYWJzKHRpdGxlID0gIkV2b2x1Y2nDs24gZGUgbGEgYXVkaWVuY2lhIiwNCiAgICBjb2xvdXIgPSAid2hpdGUiKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSA0KSkNCg0KDQpnZ3Bsb3RseShnZ19hdWRpZW5jaWFzKQ0KDQpgYGANCg0KDQojIyMgUHJlc3VwdWVzdG9zDQoNCkVsIHByZXN1cHVlc3RvIGRlIGxhcyBlc2N1ZGVyaWFzIHNpZW1wcmUgaGEgc2lkbyB1biB0ZW1hIG11eSBwb2zDqW1pY28gZW4gZWwgbXVuZG8gZGUgbGEgRjEuIEN1YW50byBtYXlvciBzZWEgZWwgcHJlc3VwdWVzdG8gZGUgdW5hIGVzY3VkZXLDrWEsIG1heW9yZXMgcG9zaWJpbGlkYWRlcyB0ZW5kcsOhIGRlIGdhbmFyIGVsIG11bmRpYWwsIHBvciBsbyBxdWUgcHVlZGUgbGxlZ2FyIGEgY3Vlc3Rpb25hcnNlIHNpLCBlbCBwaWxvdG8gZ2FuYWRvciBlcyBhcXVlbCBjb24gbWF5b3IgaGFiaWxpZGFkLCBvIGFxdWVsIHF1ZSBwb3NlZSBlbCBtb25vcGxhemEgY29uIG1heW9yIGludmVyc2nDs24gZGV0csOhcy4gIA0KDQpFbCBncsOhZmljbyBkaXNwdWVzdG8gYSBjb250aW51YWNpw7NuIG11ZXN0cmEgcXVlICxkZXNkZSAyMDE1IGEgMjAyMCwgbG9zIGHDsW9zIGVuIGxvcyBxdWUgaGEgZ2FuYWRvIE1lcmNlZGVzIGVsIG11bmRpYWwsIGxhIGVzY3VkZXLDrWEgZXJhIGNvbiBsYSBxdWUgbcOhcyBwcmVzdXB1ZXN0byBjb250YWJhLCBleGNlcHRvIGVuIDIwMTUsIGRvbmRlIGVyYSBsYSBzZWd1bmRhIGNvbiBtdXkgcG9jYSBkaWZlcmVuY2lhIGNvbiBSZWQgQnVsbC4gU2luIGVtYmFyZ28sIHRhbCB5IGNvbW8gbXVlc3RyYSBsYSBncsOhZmljYSwgc2UgZXNwZXJhIHVuIG51ZXZvIHJlZ2xhbWVudG8gcGFyYSAyMDIyLCBxdWUgaW5jbHVpcsOhIGxhIGltcGxlbWVudGFjacOzbiBkZSB1biB0ZWNobyBwcmVzdXB1ZXN0YXJpbyBkZSAxNDAgbWlsbG9uZXMgZGUgZXVyb3MsIHkgcXVlIHNlIHJlZHVjaXLDoSBhIDIwMjMgYSAxMzUgbWlsbG9uZXMsIHBhcmEgdG9kYXMgbGFzIGVzY3VkZXJpYXMuICANCg0KDQpgYGB7ciwgZXZhbCA9IFRSVUUsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LmV4dHJhPSdhbmdsZT05MCcsIGVjaG8gPSBUUlVFfQ0KDQpwcmVzdXB1ZXN0b3MgPC0gcmVhZF9leGNlbCgiZGF0b3MvcHJlc3VwdWVzdG9zLnhsc3giKQ0KDQpnZ19wcmVzdXAgPC0gZ2dwbG90KHByZXN1cHVlc3RvcywgYWVzKHllYXIsIFByZXN1cHVlc3RvLCBjb2xvciA9IEVzY3VkZXJpYSkpICsgDQogIGdlb21fcG9pbnQoKSArIGdlb21fbGluZSgpICsgDQogIGxhYnMoeCA9ICJBw7FvIiwgeSA9ICJQcmVzdXB1ZXN0byBlbiDigqwiICkgKw0KICAgIHNjYWxlX3hfY29udGludW91cygNCiAgICBicmVha3MgPSBzZXEoMjAxNSwgMjAyMywgMSksDQogICAgbGltaXRzID0gYygyMDE0LCAyMDI0KSkgKyANCiAgc2NhbGVfeV9jb250aW51b3VzKCBicmVha3MgPSBzZXEoMCwgNzAwMDAwMDAwLCAxMDAwMDAwMDApLA0KICAgIGxpbWl0cyA9IGMoMCwgNjAwMDAwMDAwKSkgICsgdGhlbWUoYXhpcy50aWNrcyA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAid2hpdGUiKSwNCiAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJ3aGl0ZSIsDQogICAgICAgIGxpbmV0eXBlID0gImJsYW5rIiksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gIndoaXRlIiwNCiAgICAgICAgbGluZXR5cGUgPSAiYmxhbmsiKSwgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsDQogICAgICAgIGZhY2UgPSAiYm9sZCIsIGNvbG91ciA9ICJjeWFuIiwgdmp1c3QgPSAwLjc1KSwNCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gIndoaXRlIiksDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsDQogICAgICAgIGZhY2UgPSAiYm9sZCIsIGNvbG91ciA9ICJjeWFuIiwgaGp1c3QgPSAwLjUsDQogICAgICAgIHZqdXN0ID0gMC43NSksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsDQogICAgICAgIGNvbG91ciA9ICJjeWFuIiksIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMsDQogICAgICAgIGZhY2UgPSAiYm9sZCIsIGNvbG91ciA9ICJjeWFuIiksDQogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIsDQogICAgICAgIGNvbG91ciA9ICJ3aGl0ZSIpLCBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiKSwNCiAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTEzIiksDQogICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiKSkgK2xhYnModGl0bGUgPSAiUFJFU1VQVUVTVE8gREUgQ0FEQSBFUVVJUE8gUE9SIFRFTVBPUkFEQSIpICsgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSBOQSksDQogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSBOQSksDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOSksDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSksDQogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIsDQogICAgICAgIGNvbG91ciA9IE5BKSwgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTEzIiwNCiAgICAgICAgY29sb3VyID0gTkEpKSArIHRoZW1lKGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiKSwNCiAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIpKSArIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTIwIiwNCiAgICBsaW5ldHlwZSA9ICJzb2xpZCIpLCBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmF5MTUiLA0KICAgIGxpbmV0eXBlID0gInNvbGlkIikpDQogDQpnZ3Bsb3RseShnZ19wcmVzdXApICNwYXJhIHF1ZSBzZWEgaW50ZXJhY3Rpdm8NCmBgYA0KDQoNCiMjIyBOYWNpb25hbGlkYWRlcyB7LnRhYnNldH0NCg0KRW4gbG9zIGNvbWllbnpvcyBkZSBsYSBGb3JtdWxhIDEsIGxhIGdyYW4gbWF5b3LDrWEgZGUgbG9zIHBpbG90b3MgZXJhbiBkZWwgY29udGluZW50ZSBldXJvcGVvLCBkZXN0YW5jbyBHcmFuIEJyZXRhw7FhLiBFc3RlIGhlY2hvIHNlIGRlYsOtYSBlbiBwYXJ0ZSBhIHF1ZSBsYSBtYXlvcsOtYSBkZSBsb3MgY2lyY3VpdG9zIHNlIGVuY29udHJhYmFuIGVuIEV1cm9wYS4gU2luIGVtYmFyZ28sIGNvbiBlbCBwYXNvIGRlIGxhcyBhw7FvcywgZWwgZGVwb3J0ZSBzZSB2b2x2acOzIGNhZGEgdmV6IG3DoXMgaW50ZXJuYWNpb25hbC4gRnVlcmEgZGUgRXVyb3BhIGRlc3RhY2EgRXN0YWRvcyBVbmlkb3MsIHNpZW5kbyBlbCBzZWd1bmRvIHBhw61zIGNvbiBtw6FzIHBpbG90b3MgZW4gbGEgaGlzdG9yaWEsIGVuIHN1ZGFtw6lyaWNhIEJyYXNpbCB5IEFyZ2VudGluYSwgZW4gQXNpYSBKYXBvbiwgeSBlbiBPY2VhbsOtYSBBdXN0cmFsaWEuIEVuIMOBZnJpY2EsIHNvbG8gaGF5IGRvcyBwYcOtc2VzIGNvbiByZXByZXNlbnRhY2nDs24sIFN1ZMOhZnJpY2EgY29uIDIzIHkgWmltYmFidWUgY29uIDQuIEVuIEVzcGHDsWEgZWwgdG90YWwgZGUgcmVwcmVzZW50YW50ZXMgaGEgc2lkbyAxNS4gQSBwZXNhciBkZSBzdSBhcGFydHVyYSwgc2lndWUgZXhpc3RpZW5kbyB1biBjbGFybyBwcmVkb21pbmlvIGV1cm9wZW8sIHBvciBlamVtcGxvIGVuIGxhIHRlbXBvcmFkYSBhY3R1YWwsIGNhc2kgMy80IGRlIGxhIHBhcnJpbGxhIHNvbiBwaWxvdG9zIGNvbiBuYWNpb25hbGlkYWQgZXVyb3BlYS4gDQoNCiMjIyMgTWFwYQ0KYGBge3J9DQoNCmdncGxvdGx5KGdnX3BpbG90b3NfcG9yX3BhaXNlcykNCg0KYGBgDQoNCiMjIyMgVGFibGEgDQoNCmBgYHtyLCBldmFsID0gVFJVRSwgZWNobyA9IFRSVUV9DQoNCnNldF9mbGV4dGFibGVfZGVmYXVsdHMoDQogIGZvbnQuc2l6ZSA9IDE1LA0KICBmb250LmNvbG9yID0gIndoaXRlIiwNCiAgdGFibGUubGF5b3V0ID0gImZpeGVkIiwgDQogIGJhY2tncm91bmQuY29sb3IgPSAiZ3JheTEzIikNCg0KZmxleF9waWxvdG8gPC0gZmxleHRhYmxlKG5hY2lvbmFsaWRhZCkNCg0Kc21hbGxfYm9yZGVyID0gZnBfYm9yZGVyKGNvbG9yPSJncmF5NTAiLCB3aWR0aCA9IDIpDQoNCmZsZXhfcGlsb3RvMSA8LSBib3JkZXJfb3V0ZXIoZmxleF9waWxvdG8sIHBhcnQ9ImFsbCIsIGJvcmRlciA9IHNtYWxsX2JvcmRlciApDQoNCg0KdGhlbWVfdmFkZXIoZmxleF9waWxvdG8xKQ0KYGBgDQoNCg0KIyMjIFBpbG90b3MgY29uIG3DoXMgdmljdG9yaWFzDQoNCkdhbmFyIHVuYSBjYXJyZXJhIGVuIEYxIHJlcHJlc2VudGEgaGFiZXIgc2lkbyBlbCBtZWpvciBwaWxvdG8gZGUgbGEgcGFycmlsbGEgZHVyYW50ZSB1biBncmFuIHByZW1pbywgeSB0aWVuZSB1biBncmFuIHZhbG9yLCBkZWJpZG8gYSBsYSBlbGV2YWRhIGNvbXBldGl0aXZpZGFkIHF1ZSBleGlzdGUgZW4gZXN0ZSBkZXBvcnRlLiBQb3IgdGFudG8sIGEgcGVzYXIgZGUgbm8gc2VyIGxhIMO6bmljYSwgZXMgdW5hIGJ1ZW5hIHZhcmlhYmxlIHBhcmEgbWVkaXIgbGFzIGNhcGFjaWRhZGVzIGRlIHVuIHBpbG90by4gICAgDQpFbCBncsOhZmljbyBzaWd1aWVudGUgbXVlc3RyYSBkaWNoYSB2YXJpYWJsZSwgbGFzIHZpY3RvcmlhcywgcGVybyBkZSBsb3MgMTYgcGlsb3RvcyBxdWUgbcOhcyBoYW4gY29uc2VndWlkbyBhIGxvIGxhcmdvIGRlIHN1IGhpc3RvcmlhLiBEZXN0YWNhbiBzb2JyZSBlbCByZXN0byBMZXdpcyBIYW1pbHRvbiwgY29uIDk4IHZpY3RvcmlhcywgeSBNaWNoYWVsIFNjaHVtYWNoZXIsIGNvbiA5MS4gRmVybmFuZG8gQWxvc25vIHNlIGVuY3VlbnRyYSBlbCBzZXh0byBjb24gMzIuIENhYmUgZGVzdGFjYXIgcXVlLCB2YXJpb3MgZGUgZXN0b3MgcGlsb3RvcyBzaWd1ZW4gZW4gYWN0aXZvLCBBbG9uc28sIFZldHRlbCB5IEhhbWlsdG9uLCBwb3IgbG8gcXVlIHBvZHLDoW4gc2VndWlyIGF1bWVudGFuZG8gc3UgcGFsbWFyw6lzLg0KDQpgYGB7ciwgZXZhbCA9IFRSVUUsIGVjaG8gPSBUUlVFfQ0KDQpnZ3Bsb3QodmljdG9yaWFzMiwgYWVzKHggPSByZW9yZGVyKGRyaXZlclJlZixzdW1hX3ZpYyksIHN1bWFfdmljKSkgKyANCiAgZ2VvbV9saW5lKHNpemU9NSwgY29sb3VyID0gImN5YW4iKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLA0KICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUsDQogICAgICAgIGNvbG91ciA9ICJ3aGl0ZSIsIGhqdXN0ID0gMCksIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTIwIiwNCiAgICAgICAgbGluZXR5cGUgPSAic29saWQiKSwgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJibGFuayIpLA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAiYmxhbmsiKSwNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJjeWFuIiksDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJjeWFuIiksDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3VyID0gIndoaXRlIiksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoY29sb3VyID0gIndoaXRlIiksDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTcsDQogICAgICAgIGNvbG91ciA9ICJ3aGl0ZSIsIGhqdXN0ID0gMC41KSwgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIsDQogICAgICAgIGNvbG91ciA9ICJncmF5MTMiLCBsaW5ldHlwZSA9ICJzb2xpZCIpLA0KICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIsDQogICAgICAgIGNvbG91ciA9ICJncmF5MTMiLCBsaW5ldHlwZSA9ICJzb2xpZCIpKSArbGFicyh0aXRsZSA9ICdQaWxvdG9zIGNvbiBtw6FzIHZpY3RvcmlhcycgLHggPSAiUGlsb3RvcyIsDQogICAgeSA9ICJOwrogdmljdG9yaWFzIikgKyB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJncmF5NTAiKSwNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsDQogICAgICAgIGNvbG91ciA9ICJjeWFuIikpICtsYWJzKHRpdGxlID0gIlBJTE9UT1MgQ09OIE3DgVMgVklDVE9SSUFTIiwNCiAgICBzdWJ0aXRsZSA9ICkgIysgdHJhbnNpdGlvbl9yZXZlYWwoZGF0ZSkNCg0KDQpgYGANCg0KDQojIyMgUmVtYW5kbyBhIGNvbnRyYWNvcnJpZW50ZQ0KDQpMb3MgYWRlbGFudGFtaWVudG9zIHNvbiB1biBlbGVtbnRvIGLDoXNpY28gZW4gbGFzIGNhcnJlcmFzLCB5IG3DoXMgZW4gbGEgRjEuIExhIGx1Y2hhIHBvciB1bmEgcG9zaWNpw7NuIHB1ZWRlIGdlbmVyYXIgbW9tZW50b3MgZGUgdGVuc2nDs24sIHRvcXVlcyBvIGFjY2lkZW50ZXMgZW4gYWxndW5hcyBvY2FzaW9uZXMsIG8gZW4gb3RyYXMgb2Nhc2lvbmVzICBwdWVkZW4gc2VyIHNpbXBsZW1lbnRlIGxpbXBpb3MuIEVuIGFtYm9zIGNhc29zLCBhw7FhZGVuIGRpbmFtaXNtbyBhIGxhcyBjYXJyZXJhcywgY29uc2lndWllbmRvIG1hbnRlbmVyIGxhIGF0ZW5jacOzbiBkZWwgZXNwZWN0YWRvci4gUG9yIGVzbywgdW5vIGRlIGxvcyBtb21lbnRvcyBtw6FzIGltcG9ydGFudGVzIHkgbcOhcyB2aXN0b3MgZGUgdW5hIGNhcnJlcmEgZXMgbGEgc2FsaWRhLCBkZWJpZG8gYSBxdWUgdG9kb3MgbG9zIHBpbG90b3MgcHJldGVuZGVuIHJlYWxpemFyIGxhIHRyYXphZGEgbcOhcyByw6FwaWRhLCBqdW50YW5kb3NlIGVuIHBvY29zIG1ldHJvcywgZSBpbmNyZW1tZW50YW5kbyBjb25zaWRlcmFibGVtZW50ZSBsb3Mgcmllc2dvcyBkZSB1bmEgY29saXNpw7NuLiAgICANCg0KRWwgc2lndWllbnRlIGdyw6FmaWNvIG11ZXN0cmEgbGFzIG1heW9yZXMgcmVtb250YWRhcyBkZSBsYSBoaXN0b3JpYSBtb2Rlcm5hIGRlIGxhIEYxLCBlcyBkZWNpciwgY2FycmVyYXMgZG9uZGUgbG9zIHBpbG90b3Mgbm9tYnJhZG9zIGNvbnNpZ3VpZXJvbiByZWFsaXphciBwaWxvdGFqZXMgYnJpbGxhbnRlcywgZGViaWRvIGEgdW4gZWxldmFkbyBuw7ptZXJvIGRlIGFkZWxhbnRhbWllbnRvcy4gRW4gcHJpbWVyIGx1Z2FyIHNlIGVuY3VlbnRyYSBsYSBjYXJyZXJhIHF1ZSByZWFsaXrDsyBWZXR0ZWwgZW4gMjAxMiBlbiBlbCBjaXJjdWl0byBkZSBZYXMgTWFyaW5hLCBjb25zaWd1aWVuZG8gcmVtb250YXIgMjEgcHVlc3Rvcy4gUGVybyBzaW4gZHVkYSwgbGEgY2FycmVyYSBtw6FzIGRlc3RhY2FkYSBlcyBsYSBsbGV2YWRvIGEgY2FibyBlbiAyMDEwIHBvciBGZXJuYW5kbyBBbG9uc28sIHF1ZSBjb25zaWd1acOzIHJlbW9udGFyIDE4IHB1ZXN0b3MgZW4gZWwgbcOhcyBxdWUgY29tcGxpY2Fkw61zaW1vIGNpcmN1aXRvIHVyYmFubyBkZSBNw7NuYWNvLg0KDQoNCg0KDQoNCg0KDQoNCg0KYGBge3IsIGV2YWwgPSBUUlVFLCBlY2hvID0gVFJVRX0NCnRydWxsaSA8LSByZWFkUE5HKCIuL2ltYWdlbmVzL3BpbG90b3MvdHJ1bGxpLnBuZyIpDQprb3ZhbGFpbmVuIDwtIHJlYWRQTkcoIi4vaW1hZ2VuZXMvcGlsb3Rvcy9rb3ZhbGFpbmVuLnBuZyIpDQp2ZXR0ZWwgPC0gcmVhZFBORygiLi9pbWFnZW5lcy9waWxvdG9zL3ZldHRlbC5wbmciKQ0KcmFpa2tvbmVuIDwtIHJlYWRQTkcoIi4vaW1hZ2VuZXMvcGlsb3Rvcy9yYWlra29uZW4ucG5nIikNCnNjaHVtYWNoZXIgPC0gcmVhZFBORygiLi9pbWFnZW5lcy9waWxvdG9zL3NjaHVtYWNoZXIucG5nIikNCmhhbWlsdG9uIDwtIHJlYWRQTkcoIi4vaW1hZ2VuZXMvcGlsb3Rvcy9oYW1pbHRvbi5wbmciKQ0KbW9udG95YSA8LSByZWFkUE5HKCIuL2ltYWdlbmVzL3BpbG90b3MvbW9udG95YS5wbmciKQ0KYWxvbnNvIDwtIHJlYWRQTkcoIi4vaW1hZ2VuZXMvcGlsb3Rvcy9hbG9uc28ucG5nIikNCg0KdHJ1bGxpX2dyb2IgPC0gcmFzdGVyR3JvYih0cnVsbGksIGludGVycG9sYXRlPVRSVUUpDQprb3ZhbGFpbmVuX2dyb2IgPC0gcmFzdGVyR3JvYihrb3ZhbGFpbmVuLCBpbnRlcnBvbGF0ZT1UUlVFKQ0KdmV0dGVsX2dyb2IgPC0gcmFzdGVyR3JvYih2ZXR0ZWwsIGludGVycG9sYXRlPVRSVUUpDQpyYWlra29uZW5fZ3JvYiA8LSByYXN0ZXJHcm9iKHJhaWtrb25lbiwgaW50ZXJwb2xhdGU9VFJVRSkNCnNjaHVtYWNoZXJfZ3JvYiA8LSByYXN0ZXJHcm9iKHNjaHVtYWNoZXIsIGludGVycG9sYXRlPVRSVUUpDQpoYW1pbHRvbl9ncm9iIDwtIHJhc3Rlckdyb2IoaGFtaWx0b24sIGludGVycG9sYXRlPVRSVUUpDQptb250b3lhX2dyb2IgPC0gcmFzdGVyR3JvYihtb250b3lhLCBpbnRlcnBvbGF0ZT1UUlVFKQ0KYWxvbnNvX2dyb2IgPC0gcmFzdGVyR3JvYihhbG9uc28sIGludGVycG9sYXRlPVRSVUUpDQoNCg0KZ2dyZW1vbnRhZG9zIDwtIGdncGxvdChwdWVzdG9zX3JlbW9udF9waWxvdG9fcmVjaWVudCwgYWVzKHggPSByZW9yZGVyKGRyaXZlclJlZiwgcmVtb250YWRvcyksIHJlbW9udGFkb3MpKSAgKyBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKyBjb29yZF9mbGlwKCkgKyBsYWJzKHggPSAiUGlsb3RvcyIsIHkgPSAiTsK6IGRlIHB1ZXN0b3MgcmVtb250YWRvcyIgKSArIGFubm90YXRpb25fY3VzdG9tKGFsb25zb19ncm9iLCB4bWluPSAtMTUsIHhtYXg9MTcsIHltaW49IDE4LCB5bWF4PTIwKSArDQogIGFubm90YXRpb25fY3VzdG9tKGtvdmFsYWluZW5fZ3JvYiwgeG1pbj0gLTIwLCB4bWF4PTI0LCB5bWluPSAxOC42NSwgeW1heD0yMCkgKw0KICBhbm5vdGF0aW9uX2N1c3RvbShtb250b3lhX2dyb2IsIHhtaW49IC0yNi43LCB4bWF4PTMzLCB5bWluPSAxOCwgeW1heD0yMS4yKSArDQogIGFubm90YXRpb25fY3VzdG9tKHRydWxsaV9ncm9iLCB4bWluPSAtMzIsIHhtYXg9NDAuLCB5bWluPSAxOC4zLCB5bWF4PTE5LjU1KSArDQogIGFubm90YXRpb25fY3VzdG9tKGhhbWlsdG9uX2dyb2IsIHhtaW49IC0zMiwgeG1heD00Mi4yLCB5bWluPSAxOSwgeW1heD0yMS44KSArDQogIGFubm90YXRpb25fY3VzdG9tKHNjaHVtYWNoZXJfZ3JvYiwgeG1pbj0gLTMyLCB4bWF4PTQ0LjEsIHltaW49IDE5LjIsIHltYXg9MjAuNSkgKw0KICBhbm5vdGF0aW9uX2N1c3RvbShyYWlra29uZW5fZ3JvYiwgeG1pbj0gLTMyLCB4bWF4PTQ2LjEsIHltaW49IDE5LCB5bWF4PTIxKSArDQogIGFubm90YXRpb25fY3VzdG9tKHZldHRlbF9ncm9iLCB4bWluPSAtMzIsIHhtYXg9NDguMSwgeW1pbj0gMTksIHltYXg9MjEuMikgKw0KICAgIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAid2hpdGUiKSwNCiAgICBheGlzLnRpY2tzID0gZWxlbWVudF9saW5lKGNvbG91ciA9IE5BKSwNCiAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJjeWFuIiwNCiAgICAgICAgbGluZXR5cGUgPSAiYmxhbmsiKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTIwIiksDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLA0KICAgICAgICBjb2xvdXIgPSAiZ3JheTUwIiksIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEsDQogICAgICAgIGNvbG91ciA9ICJjeWFuIiksIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJjeWFuIiksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoY29sb3VyID0gImN5YW4iKSwNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSwNCiAgICAgICAgZmFjZSA9ICJib2xkIiwgY29sb3VyID0gImN5YW4iLCBoanVzdCA9IDAuNDUsDQogICAgICAgIHZqdXN0ID0gMC43NSksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiLA0KICAgICAgICBsaW5ldHlwZSA9ICJzb2xpZCIpLCBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiLA0KICAgICAgICBjb2xvdXIgPSAiY3lhbiIsIGxpbmV0eXBlID0gInNvbGlkIikpICtsYWJzKHRpdGxlID0gIk1BWU9SRVMgUkVNT05UQURBUyBFTiBMQSBISVNUT1JJQSIpDQogIA0KDQpnZ3JlbW9udGFkb3MNCg0KYGBgDQoNCiMjIyBNdW5kaWFsZXMgcG9yIGVzY3VkZXJpYXMgeSBwaWxvdG9zIHsudGFic2V0fQ0KDQpFbCBtYXlvciBwcmVtaW8gcGFyYSB1biBwaWxvdG8geSB1bmEgZXNjdWRlcsOtYSBlcyBhbHphcnNlIGNvbiBlbCB0w610dWxvIGRlIGNhbXBlw7NuIGRlbCBtdW5kaWFsIGFsIGZpbmFsIGRlIHVuYSB0ZW1wb3JhZGEsIG1vc3RyYW5kbyBhbCBlcXVpcG8geSBwaWxvdG8gY29uIG1heW9yIHJlZ3VsYXJpZGFkLCB5IGVsIHF1ZSBlbiBsYSBncmFuIHBhcnRlIGRlIGxhcyBvY2FzaW9uZXMgc2VhIGVsIG1lam9yIHZlaMOtY3VsbyBkZSBlc2UgYcOxby4gIA0KDQpMYSBlc2N1ZGVyw61hIG3DoXMgZ2FsYXJkb25hZGEgZXMgTWNMYXJlbiBjb24gOSBjYW1wZW9uYXRvcyBtdW5kaWFsZXMsIGNvbnNlZ3VpZG9zIHN1IGdyYW4gbWF5b3LDrWEgZW4gbGEgw6lwb2NhIGRlIGxvcyA4MC4gTGUgc2lndWUgRmVycmFyaSwgY29uIDggdMOtdHVsb3MsIHNpZW5kbyBjb25zaWRlcmFkYSBwb3IgbXVjaG9zLCBsYSBlc2N1ZGVyw61hIG3DoXMgZW1ibGVtw6F0aWNhLiBEZW50cm8gZGUgYW1iYXMgZXNjZGVyaWFzLCBhcGFyZWNlbiBwaWxvdHMgcXVlIGRlc3RhcGFuIHNvYnJlIGVsIHJlc3RvLiBFbiBlbCBjYXNvIGRlIE1jTGFyZW4sIHRhbnRvIFByb3N0IGNvbW8gU2VubmEgc29uIGxvcyBwaWxvdG9zIG3DoXMgcmVsZXZhbnRlcywgeSBlbiBlbCBjYXNvIGRlIEZlcnJhcmksIE1pY2hhZWwgU2NodW1hY2hlci4NCg0KDQojIyMjIEVuIHZhbG9yZXMgcmVsYXRpdm9zDQoNCmBgYHtyLCBldmFsID0gVFJVRSwgZWNobyA9IFRSVUUsIGluY2x1ZGUgPSBGQUxTRX0NCiNkYXRvcyBkZSBlc2N1ZGVyaWFzIHBhIHF1aWVuIHF1aWVyYSBoYWNlciBhbGdvDQplc2N1ZGVyaWFzIDwtIHJpbzo6aW1wb3J0KGZpbGUgPSAiLi9kYXRvcy9jb25zdHJ1Y3RvcnMuY3N2IikNCmVzY3VkZXJpYXMyIDwtIHJpbzo6aW1wb3J0KGZpbGUgPSAiLi9kYXRvcy9jb25zdHJ1Y3Rvcl9zdGFuZGluZ3MuY3N2IikNCnJlc3VsdF9lc2N1ZGVyaWFzIDwtIHJpbzo6aW1wb3J0KGZpbGUgPSAiLi9kYXRvcy9jb25zdHJ1Y3Rvcl9yZXN1bHRzLmNzdiIpDQoNCnBpbG90b3MgPC0gcmlvOjppbXBvcnQoZmlsZSA9ICIuL2RhdG9zL2RyaXZlcnMuY3N2IikNCnJlc3VsdGFkb3MgPC0gcmlvOjppbXBvcnQoZmlsZSA9ICIuL2RhdG9zL3Jlc3VsdHMuY3N2IikNCmNhcnJlcmFzIDwtIHJpbzo6aW1wb3J0KGZpbGUgPSAiLi9kYXRvcy9yYWNlcy5jc3YiKQ0KI2VzY3VkZXJpYXNlc3AgPC0gZXNjdWRlcmlhcyAlPiUgZmlsdGVyKG5hdGlvbmFsaXR5ID09ICJTcGFuaXNoIikgI2VzY3VkZXJpYXMgZXNwYcOxb2xhcw0KDQpjYW1wZW9uZXNfZXNjIDwtIGZ1bGxfam9pbihwaWxvdG9zLCByZXN1bHRhZG9zLCBjKCJkcml2ZXJJZCIgPSAiZHJpdmVySWQiKSkgJT4lIGZ1bGxfam9pbiguLCBjYXJyZXJhcywgYygicmFjZUlkIiA9ICJyYWNlSWQiKSkgJT4lIHNlbGVjdChkcml2ZXJJZCwgZHJpdmVyUmVmLCBuYXRpb25hbGl0eSwgY29uc3RydWN0b3JJZCwgcG9pbnRzLCB5ZWFyLCByb3VuZCkgJT4lIGZ1bGxfam9pbiguLCBlc2N1ZGVyaWFzLCBjKCJjb25zdHJ1Y3RvcklkIiA9ICJjb25zdHJ1Y3RvcklkIikpICU+JSBzZWxlY3QoZHJpdmVySWQsIGRyaXZlclJlZiwgbmF0aW9uYWxpdHkueCwgY29uc3RydWN0b3JJZCwgcG9pbnRzLCB5ZWFyLCBuYW1lLCByb3VuZCkgJT4lICBncm91cF9ieSh5ZWFyLCBkcml2ZXJSZWYpICU+JSAgbXV0YXRlKHB1bnRvc190b3RhbGVzID0gY3Vtc3VtKHBvaW50cykpICU+JSB1bmdyb3VwKCkgJT4lIGdyb3VwX2J5KHllYXIpICU+JSBzbGljZV9tYXgocHVudG9zX3RvdGFsZXMsIG49MSkgJT4lIHNlbGVjdChuYW1lLCBkcml2ZXJSZWYpICU+JSBncm91cF9ieShuYW1lLCBkcml2ZXJSZWYpICU+JSBtdXRhdGUodG90YWxfY2FtcCA9IHN1bSggTk4gPSBuKCkpKSAlPiUgYXJyYW5nZShuYW1lKSANCg0KDQoNCg0KbGlicmFyeSh0cmVlbWFwKQ0KbGlicmFyeShkM3RyZWVSKQ0KDQoNCiMgYmFzaWMgdHJlZW1hcA0KZ2dfZXNjX2NhbXBlb25lcyA8LSB0cmVlbWFwKGNhbXBlb25lc19lc2MsDQogICAgICAgICAgICBpbmRleD1jKCJuYW1lIiwiZHJpdmVyUmVmIiksDQogICAgICAgICAgICB2U2l6ZT0idG90YWxfY2FtcCIsDQogICAgICAgICAgICB0eXBlPSJpbmRleCIsDQogICAgICAgICAgICB2Q29sb3IgPSAibmFtZSIsDQogICAgICAgICAgICBmb250c2l6ZS5sYWJlbHM9YygxNSwyMCksDQogICAgICAgICAgICBiZy5sYWJlbHM9YygidHJhbnNwYXJlbnQiKSwNCiAgICAgICAgICAgIHBhbGV0dGUgPSAiU2V0MiIsDQogICAgICAgICAgICBhbGlnbi5sYWJlbHM9bGlzdCgNCiAgICAgICAgICAgICAgYygiY2VudGVyIiwgImNlbnRlciIpLCANCiAgICAgICAgICAgICAgYygiY2VudGVyIiwgImJvdHRvbSIpKSwNCiAgICAgICAgICAgIHRpdGxlID0gIkVzY3VkZXLDrWFzIGNvbiBtw6FzIGNhbXBlb25lcyIsDQogICAgICAgICAgICB0aXRsZS5sZWdlbmQgPSAiRXNjdWRlcsOtYXMiKSAgIA0KDQpgYGANCg0KDQpgYGB7ciwgZXZhbCA9IFRSVUUsIGVjaG8gPSBUUlVFfQ0KI2RhdG9zIGRlIGVzY3VkZXJpYXMgcGEgcXVpZW4gcXVpZXJhIGhhY2VyIGFsZ28NCiNlc2N1ZGVyaWFzIDwtIHJpbzo6aW1wb3J0KGZpbGUgPSAiLi9kYXRvcy9jb25zdHJ1Y3RvcnMuY3N2IikNCiNlc2N1ZGVyaWFzMiA8LSByaW86OmltcG9ydChmaWxlID0gIi4vZGF0b3MvY29uc3RydWN0b3Jfc3RhbmRpbmdzLmNzdiIpDQojcmVzdWx0X2VzY3VkZXJpYXMgPC0gcmlvOjppbXBvcnQoZmlsZSA9ICIuL2RhdG9zL2NvbnN0cnVjdG9yX3Jlc3VsdHMuY3N2IikNCg0KI3BpbG90b3MgPC0gcmlvOjppbXBvcnQoZmlsZSA9ICIuL2RhdG9zL2RyaXZlcnMuY3N2IikNCiNyZXN1bHRhZG9zIDwtIHJpbzo6aW1wb3J0KGZpbGUgPSAiLi9kYXRvcy9yZXN1bHRzLmNzdiIpDQojY2FycmVyYXMgPC0gcmlvOjppbXBvcnQoZmlsZSA9ICIuL2RhdG9zL3JhY2VzLmNzdiIpDQojZXNjdWRlcmlhc2VzcCA8LSBlc2N1ZGVyaWFzICU+JSBmaWx0ZXIobmF0aW9uYWxpdHkgPT0gIlNwYW5pc2giKSAjZXNjdWRlcmlhcyBlc3Bhw7FvbGFzDQoNCiNjYW1wZW9uZXNfZXNjIDwtIGZ1bGxfam9pbihwaWxvdG9zLCByZXN1bHRhZG9zLCBjKCJkcml2ZXJJZCIgPSAiZHJpdmVySWQiKSkgJT4lIGZ1bGxfam9pbiguLCBjYXJyZXJhcywgYygicmFjZUlkIiA9ICJyYWNlSWQiKSkgJT4lIHNlbGVjdChkcml2ZXJJZCwgZHJpdmVyUmVmLCBuYXRpb25hbGl0eSwgY29uc3RydWN0b3JJZCwgcG9pbnRzLCB5ZWFyLCByb3VuZCkgJT4lIGZ1bGxfam9pbiguLCBlc2N1ZGVyaWFzLCBjKCJjb25zdHJ1Y3RvcklkIiA9ICJjb25zdHJ1Y3RvcklkIikpICU+JSBzZWxlY3QoZHJpdmVySWQsIGRyaXZlclJlZiwgbmF0aW9uYWxpdHkueCwgY29uc3RydWN0b3JJZCwgcG9pbnRzLCB5ZWFyLCBuYW1lLCByb3VuZCkgJT4lICBncm91cF9ieSh5ZWFyLCBkcml2ZXJSZWYpICU+JSAgbXV0YXRlKHB1bnRvc190b3RhbGVzID0gY3Vtc3VtKHBvaW50cykpICU+JSB1bmdyb3VwKCkgJT4lIGdyb3VwX2J5KHllYXIpICU+JSBzbGljZV9tYXgocHVudG9zX3RvdGFsZXMsIG49MSkgJT4lIHNlbGVjdChuYW1lLCBkcml2ZXJSZWYpICU+JSBncm91cF9ieShuYW1lLCBkcml2ZXJSZWYpICU+JSBtdXRhdGUodG90YWxfY2FtcCA9IHN1bSggTk4gPSBuKCkpKSAlPiUgYXJyYW5nZShuYW1lKSANCg0KDQoNCg0KI2xpYnJhcnkodHJlZW1hcCkNCiNsaWJyYXJ5KGQzdHJlZVIpDQoNCg0KIyBiYXNpYyB0cmVlbWFwDQojZ2dfZXNjX2NhbXBlb25lcyA8LSB0cmVlbWFwKGNhbXBlb25lc19lc2MsDQogICAgICAgICAgICAjaW5kZXg9YygibmFtZSIsImRyaXZlclJlZiIpLA0KICAgICAgICAgICAgI3ZTaXplPSJ0b3RhbF9jYW1wIiwNCiAgICAgICAgICAgICN0eXBlPSJpbmRleCIsDQogICAgICAgICAgICAjdkNvbG9yID0gIm5hbWUiLA0KICAgICAgICAgICAgI2ZvbnRzaXplLmxhYmVscz1jKDI1LDE3KSwNCiAgICAgICAgICAgICNiZy5sYWJlbHM9YygidHJhbnNwYXJlbnQiKSwNCiAgICAgICAgICAgICNwYWxldHRlID0gIlNldDIiLA0KICAgICAgICAgICAgI2FsaWduLmxhYmVscz1saXN0KA0KICAgICAgICAgICAgICAjYygiY2VudGVyIiwgImNlbnRlciIpLCANCiAgICAgICAgICAgICAgI2MoImNlbnRlciIsICJib3R0b20iKSksDQogICAgICAgICAgICAjdGl0bGUgPSAiRXNjdWRlcsOtYXMgY29uIG3DoXMgY2FtcGVvbmVzIiwNCiAgICAgICAgICAgICN0aXRsZS5sZWdlbmQgPSAiRXNjdWRlcsOtYXMiKSAgIA0KDQpgYGANCg0KYGBge3IsIGZpZy5hbGlnbj0nY2VudGVyJ30NCg0KaW50ZXJfY2FtcCA8LSBkM3RyZWUyKGdnX2VzY19jYW1wZW9uZXMgLCAgcm9vdG5hbWUgPSAiRXNjdWRlcsOtYXMgeSBDYW1wZW9uZXMiKQ0KaW50ZXJfY2FtcA0KDQoNCmBgYA0KDQoNCiMjIyMgRW4gdmFsb3JlcyBhYnNvbHV0b3MNCg0KYGBge3J9DQpjYW1wZW9uZXNfZXNjIDwtIGZ1bGxfam9pbihwaWxvdG9zLCByZXN1bHRhZG9zLCBjKCJkcml2ZXJJZCIgPSAiZHJpdmVySWQiKSkgJT4lIGZ1bGxfam9pbiguLCBjYXJyZXJhcywgYygicmFjZUlkIiA9ICJyYWNlSWQiKSkgJT4lIHNlbGVjdChkcml2ZXJJZCwgZHJpdmVyUmVmLCBuYXRpb25hbGl0eSwgY29uc3RydWN0b3JJZCwgcG9pbnRzLCB5ZWFyLCByb3VuZCkgJT4lIGZ1bGxfam9pbiguLCBlc2N1ZGVyaWFzLCBjKCJjb25zdHJ1Y3RvcklkIiA9ICJjb25zdHJ1Y3RvcklkIikpICU+JSBzZWxlY3QoZHJpdmVySWQsIGRyaXZlclJlZiwgbmF0aW9uYWxpdHkueCwgY29uc3RydWN0b3JJZCwgcG9pbnRzLCB5ZWFyLCBuYW1lLCByb3VuZCkgJT4lICBncm91cF9ieSh5ZWFyLCBkcml2ZXJSZWYpICU+JSAgbXV0YXRlKHB1bnRvc190b3RhbGVzID0gY3Vtc3VtKHBvaW50cykpICU+JSB1bmdyb3VwKCkgJT4lIGdyb3VwX2J5KHllYXIpICU+JSBzbGljZV9tYXgocHVudG9zX3RvdGFsZXMsIG49MSkgJT4lIHVuZ3JvdXAoKSAlPiUgY291bnQobmFtZSkgJT4lIGFycmFuZ2UoZGVzYyhuKSkNCg0KY2FtcGVvbmVzX2VzYyRuPWFzLmZhY3RvcihjYW1wZW9uZXNfZXNjJG4pDQoNCmdnX2NhbXBlb25lc19lcyA8LSBnZ3Bsb3QoY2FtcGVvbmVzX2VzYywgYWVzKHg9bmFtZSwgeT1uKSkgKw0KICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHdpZHRoPTIsIGNvbG9yPSJ3aGl0ZSIpICsgDQogIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTEzIiksDQogICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTEzIiksDQogICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTEzIiksDQogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTEzIiksDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiQm9va21hbiIsDQogICAgICAgIHNpemUgPSA4LCBmYWNlID0gImJvbGQiKSwgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsDQogICAgICAgIGNvbG91ciA9ICJjeWFuIiksIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJncmF5MTMiKSwNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAiZ3JheTEzIiksDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiQm9va21hbiIsDQogICAgICAgIHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiwgY29sb3VyID0gImN5YW4iLCBoanVzdD0wLjUpLA0KICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LA0KICAgICAgICBmYWNlID0gImJvbGQiLCBjb2xvdXIgPSAiY3lhbiIpLA0KICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCwNCiAgICAgICAgZmFjZSA9ICJib2xkIiwgY29sb3VyID0gImdyYXkxMyIpLA0KICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiLA0KICAgICAgICBjb2xvdXIgPSAiZ3JheTEzIiwgbGluZXR5cGUgPSAic29saWQiKSwNCiAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiLA0KICAgICAgICBjb2xvdXIgPSAiZ3JheTEzIiwgbGluZXR5cGUgPSAic29saWQiKSwNCiAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiY3lhbiIpLA0KICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTEzIikpICtsYWJzKHRpdGxlID0gIkNBTVBFT05BVE9TIFBPUiBFU0NVREVSSUEiLA0KICAgIHggPSBOVUxMLCB5ID0gTlVMTCkNCg0KDQpnZ3Bsb3RseShnZ19jYW1wZW9uZXNfZXMpDQoNCmBgYA0KDQoNCiAgDQojIyMgTXVuZGlhbGVzIHBvciBwaWxvdG9zIHkgbmFjaW9uYWxpZGFkICANCg0KU2kgYW5hbGl6YW1vcyBsb3MgY2FtcGVvbmF0b3MgbXVuZGlhbGVzIHBvciBwaWxvdG9zLCBoYXkgMyBub21icmVzIHF1ZSBzZSBhbHphbiBzb2JyZSBlbCByZXN0by4gTWljaGFlbCBTY2h1bWFjaGVyLCBjb24gOSB0w610dWxvcyBtdW5kaWFsZXMsIFByb3N0IGNvbiA4IHkgSGFtaWx0b24gY29uIDcuIEEgbml2ZWwgbmFjaW9uYWwsIEdyYW4gQnJldGHDsWEgc2UgYWx6YSBjbGFyYW1lbnRlIGNvbW8gZWwgcGHDrXMgY29uIG3DoXMgdGl0dWxvcyBtdW5kaWFsZXMsIG11eSBwb3IgZW5jaW1hIGRlbCByZXN0byBkZSBwYWlzZXMuIA0KDQpgYGB7ciwgZXZhbCA9IFRSVUUsIGVjaG8gPSBUUlVFfQ0KDQoNCmlkIDwtIHJvd25hbWVzKGNhbXBlb25lcykNCmNhbXBlb25lcyA8LSBjYmluZChpZD1pZCwgY2FtcGVvbmVzKQ0KY2FtcGVvbmVzWywgYygxKV0gPC0gc2FwcGx5KGNhbXBlb25lc1ssIGMoMSldLCBhcy5udW1lcmljKQ0KDQpsYWJlbF9jYW1wZW9uZXMgPC0gY2FtcGVvbmVzDQpudW1iZXJfb2ZfYmFyIDwtIG5yb3cobGFiZWxfY2FtcGVvbmVzKQ0KDQphbmdsZSA8LSA5MCAtIDM2MCAqIChsYWJlbF9jYW1wZW9uZXMkaWQtMC41KSAvbnVtYmVyX29mX2JhciAgICANCmxhYmVsX2NhbXBlb25lcyRoanVzdCA8LSBpZmVsc2UoIGFuZ2xlIDwgLTkwLCAxLCAwKQ0KbGFiZWxfY2FtcGVvbmVzJGFuZ2xlIDwtIGlmZWxzZShhbmdsZSA8IC05MCwgYW5nbGUrMTgwLCBhbmdsZSkNCg0KYmFzZV9jYW1wZW9uZXMgPC0gY2FtcGVvbmVzICU+JSANCiAgZ3JvdXBfYnkobmF0aW9uYWxpdHkueCkgJT4lIA0KICBzdW1tYXJpc2Uoc3RhcnQ9bWluKGlkKSwgZW5kPW1heChpZCkpICU+JSANCiAgcm93d2lzZSgpICU+JSANCiAgbXV0YXRlKHRpdGxlPW1lYW4oYyhzdGFydCwgZW5kKSkpDQoNCmdyaWRfY2FtcGVvbmVzIDwtIGJhc2VfY2FtcGVvbmVzDQpncmlkX2NhbXBlb25lcyRlbmQgPC0gZ3JpZF9jYW1wZW9uZXMkZW5kWyBjKCBucm93KGdyaWRfY2FtcGVvbmVzKSwgMTpucm93KGdyaWRfY2FtcGVvbmVzKS0xKV0gKyAxDQpncmlkX2NhbXBlb25lcyRzdGFydCA8LSBncmlkX2NhbXBlb25lcyRzdGFydCAtIDENCmdyaWRfY2FtcGVvbmVzIDwtIGdyaWRfY2FtcGVvbmVzWy0xLF0NCg0KZ2dfY2lyY192aWN0b3JpYXMgPC0gZ2dwbG90KGNhbXBlb25lcywgYWVzKHg9YXMuZmFjdG9yKHllYXIpLCB5PXRvdGFsX2NhbXBlb25hdG9zLCBmaWxsPW5hdGlvbmFsaXR5LngsIGNvbG9yID0gbmF0aW9uYWxpdHkueCkpICsgZ2VvbV9iYXIoYWVzKHg9YXMuZmFjdG9yKGlkKSwgeT10b3RhbF9jYW1wZW9uYXRvcywgZmlsbD1uYXRpb25hbGl0eS54KSwgc3RhdD0iaWRlbnRpdHkiLCBhbHBoYT0wLjUpICsNCiAgDQogIGdlb21fc2VnbWVudChkYXRhPWdyaWRfY2FtcGVvbmVzLCBhZXMoeCA9IDAsIHkgPSA4LCB4ZW5kID0gMzIsIHllbmQgPSA4KSwgY29sb3VyID0gImdyZXkiLCBhbHBoYT0xLCBzaXplPTAuMyAsIGluaGVyaXQuYWVzID0gRkFMU0UgKSArDQogIGdlb21fc2VnbWVudChkYXRhPWdyaWRfY2FtcGVvbmVzLCBhZXMoeCA9IDAsIHkgPSA2LCB4ZW5kID0gMzIsIHllbmQgPSA2KSwgY29sb3VyID0gImdyZXkiLCBhbHBoYT0xLCBzaXplPTAuMyAsIGluaGVyaXQuYWVzID0gRkFMU0UgKSArDQogIGdlb21fc2VnbWVudChkYXRhPWdyaWRfY2FtcGVvbmVzLCBhZXMoeCA9IDAsIHkgPSA0LCB4ZW5kID0gMzIsIHllbmQgPSA0KSwgY29sb3VyID0gImdyZXkiLCBhbHBoYT0xLCBzaXplPTAuMyAsIGluaGVyaXQuYWVzID0gRkFMU0UgKSArDQogIGdlb21fc2VnbWVudChkYXRhPWdyaWRfY2FtcGVvbmVzLCBhZXMoeCA9IDAsIHkgPSAyLCB4ZW5kID0gMzIsIHllbmQgPSAyKSwgY29sb3VyID0gImdyZXkiLCBhbHBoYT0xLCBzaXplPTAuMyAsIGluaGVyaXQuYWVzID0gRkFMU0UgKSArDQogIA0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSByZXAobWF4KGNhbXBlb25lcyRpZCksNCksIHkgPSBjKDIsIDQsIDYsIDgpLCBsYWJlbCA9IGMoIjIiLCAiNCIsICI2IiwgIjgiKSAsIGNvbG9yPSJ3aGl0ZSIsIHNpemU9MyAsIGFuZ2xlPTAsIGZvbnRmYWNlPSJib2xkIiwgaGp1c3Q9MSkgKw0KICANCiAgIGdlb21fYmFyKGFlcyh4PWFzLmZhY3RvcihpZCksIHk9dG90YWxfY2FtcGVvbmF0b3MsIGZpbGw9bmF0aW9uYWxpdHkueCksIHN0YXQ9ImlkZW50aXR5IiwgYWxwaGE9MC41KSArDQogIHlsaW0oLTEwLDIxKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBsb3QubWFyZ2luID0gdW5pdChyZXAoLTEsNCksICJjbSIpICkgKw0KICBjb29yZF9wb2xhcigpICsgDQogIGdlb21fdGV4dChkYXRhPWxhYmVsX2NhbXBlb25lcywgYWVzKHg9aWQsIHk9MTAsIGxhYmVsPWRyaXZlclJlZiwgaGp1c3Q9aGp1c3QpLCBjb2xvcj0id2hpdGUiLCBmb250ZmFjZT0iYm9sZCIsYWxwaGE9MC42LCBzaXplPTMuNSwgYW5nbGU9IGxhYmVsX2NhbXBlb25lcyRhbmdsZSwgaW5oZXJpdC5hZXMgPSBGQUxTRSApICsNCg0KICBnZW9tX3NlZ21lbnQoZGF0YT1ncmlkX2NhbXBlb25lcywgYWVzKHggPSAwLjcwLCB5ID0gLTEsIHhlbmQgPSAyLjQ1LCB5ZW5kID0gLTEpLCBjb2xvdXIgPSAid2hpdGUiLCBhbHBoYT0xLCBzaXplPTAuMyAsIGluaGVyaXQuYWVzID0gRkFMU0UgKSAgKw0KICBnZW9tX3NlZ21lbnQoZGF0YT1ncmlkX2NhbXBlb25lcywgYWVzKHggPSAyLjYsIHkgPSAtMSwgeGVuZCA9IDMuNTUsIHllbmQgPSAtMSksIGNvbG91ciA9ICJ3aGl0ZSIsIGFscGhhPTEsIHNpemU9MC4zICwgaW5oZXJpdC5hZXMgPSBGQUxTRSApICsNCiAgZ2VvbV9zZWdtZW50KGRhdGE9Z3JpZF9jYW1wZW9uZXMsIGFlcyh4ID0gMy42NSwgeSA9IC0xLCB4ZW5kID0gNS40NSwgeWVuZCA9IC0xKSwgY29sb3VyID0gIndoaXRlIiwgYWxwaGE9MSwgc2l6ZT0wLjMgLCBpbmhlcml0LmFlcyA9IEZBTFNFICkgKw0KICBnZW9tX3NlZ21lbnQoZGF0YT1ncmlkX2NhbXBlb25lcywgYWVzKHggPSA1LjU1LCB5ID0gLTEsIHhlbmQgPSA3LjM1LCB5ZW5kID0gLTEpLCBjb2xvdXIgPSAid2hpdGUiLCBhbHBoYT0xLCBzaXplPTAuMyAsIGluaGVyaXQuYWVzID0gRkFMU0UgKSArDQogIGdlb21fc2VnbWVudChkYXRhPWdyaWRfY2FtcGVvbmVzLCBhZXMoeCA9IDcuNSwgeSA9IC0xLCB4ZW5kID0gMTAuNTAsIHllbmQgPSAtMSksIGNvbG91ciA9ICJ3aGl0ZSIsIGFscGhhPTEsIHNpemU9MC4zICwgaW5oZXJpdC5hZXMgPSBGQUxTRSApICsNCiAgZ2VvbV9zZWdtZW50KGRhdGE9Z3JpZF9jYW1wZW9uZXMsIGFlcyh4ID0gMTAuNywgeSA9IC0xLCB4ZW5kID0gMTkuMjAsIHllbmQgPSAtMSksIGNvbG91ciA9ICJ3aGl0ZSIsIGFscGhhPTEsIHNpemU9MC4zICwgaW5oZXJpdC5hZXMgPSBGQUxTRSApICsNCiAgZ2VvbV9zZWdtZW50KGRhdGE9Z3JpZF9jYW1wZW9uZXMsIGFlcyh4ID0gMTkuNCwgeSA9IC0xLCB4ZW5kID0gMjAuMywgeWVuZCA9IC0xKSwgY29sb3VyID0gIndoaXRlIiwgYWxwaGE9MSwgc2l6ZT0wLjMgLCBpbmhlcml0LmFlcyA9IEZBTFNFICkgKw0KICBnZW9tX3NlZ21lbnQoZGF0YT1ncmlkX2NhbXBlb25lcywgYWVzKHggPSAyMC40NSwgeSA9IC0xLCB4ZW5kID0gMjMuNCwgeWVuZCA9IC0xKSwgY29sb3VyID0gIndoaXRlIiwgYWxwaGE9MSwgc2l6ZT0wLjMgLCBpbmhlcml0LmFlcyA9IEZBTFNFICkgKyANCiAgZ2VvbV9zZWdtZW50KGRhdGE9Z3JpZF9jYW1wZW9uZXMsIGFlcyh4ID0gMjMuNjUsIHkgPSAtMSwgeGVuZCA9IDI0LjM1LCB5ZW5kID0gLTEpLCBjb2xvdXIgPSAid2hpdGUiLCBhbHBoYT0xLCBzaXplPTAuMyAsIGluaGVyaXQuYWVzID0gRkFMU0UgKSArIA0KICBnZW9tX3NlZ21lbnQoZGF0YT1ncmlkX2NhbXBlb25lcywgYWVzKHggPSAyNC42MCwgeSA9IC0xLCB4ZW5kID0gMjcsIHllbmQgPSAtMSksIGNvbG91ciA9ICJ3aGl0ZSIsIGFscGhhPTEsIHNpemU9MC4zICwgaW5oZXJpdC5hZXMgPSBGQUxTRSApICsNCiAgZ2VvbV9zZWdtZW50KGRhdGE9Z3JpZF9jYW1wZW9uZXMsIGFlcyh4ID0gMjcuMiwgeSA9IC0xLCB4ZW5kID0gMjkuNSwgeWVuZCA9IC0xKSwgY29sb3VyID0gIndoaXRlIiwgYWxwaGE9MSwgc2l6ZT0wLjMgLCBpbmhlcml0LmFlcyA9IEZBTFNFICkgKw0KICBnZW9tX3NlZ21lbnQoZGF0YT1ncmlkX2NhbXBlb25lcywgYWVzKHggPSAyOS43LCB5ID0gLTEsIHhlbmQgPSAzMC41LCB5ZW5kID0gLTEpLCBjb2xvdXIgPSAid2hpdGUiLCBhbHBoYT0xLCBzaXplPTAuMyAsIGluaGVyaXQuYWVzID0gRkFMU0UgKSArIA0KICBnZW9tX3NlZ21lbnQoZGF0YT1ncmlkX2NhbXBlb25lcywgYWVzKHggPSAzMC43LCB5ID0gLTEsIHhlbmQgPSAzMS41LCB5ZW5kID0gLTEpLCBjb2xvdXIgPSAid2hpdGUiLCBhbHBoYT0xLCBzaXplPTAuMyAsIGluaGVyaXQuYWVzID0gRkFMU0UgKSArDQogIGdlb21fc2VnbWVudChkYXRhPWdyaWRfY2FtcGVvbmVzLCBhZXMoeCA9IDMxLjcsIHkgPSAtMSwgeGVuZCA9IDMyLjUsIHllbmQgPSAtMSksIGNvbG91ciA9ICJ3aGl0ZSIsIGFscGhhPTEsIHNpemU9MC4zICwgaW5oZXJpdC5hZXMgPSBGQUxTRSApICsNCiAgZ2VvbV9zZWdtZW50KGRhdGE9Z3JpZF9jYW1wZW9uZXMsIGFlcyh4ID0gMzIuNywgeSA9IC0xLCB4ZW5kID0gMzMuNSwgeWVuZCA9IC0xKSwgY29sb3VyID0gIndoaXRlIiwgYWxwaGE9MSwgc2l6ZT0wLjMgLCBpbmhlcml0LmFlcyA9IEZBTFNFICkgKyB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAid2hpdGUiKSwNCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoIGNvbG91ciA9ICJ3aGl0ZSIpLCANCiAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiLCBjb2xvdXIgPSAiZ3JheTEzIiksDQogICAgbGVnZW5kLmtleSA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIpLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsDQogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIgLCBjb2xvdXIgPSAiZ3JheTEzIiksDQogICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTEzIiAsIGNvbG91ciA9ICJncmF5MTMiKSkrbGFicyhjb2xvdXIgPSAiTmFjaW9uYWxpZGFkIiwgZmlsbCA9ICJOYWNpb25hbGlkYWQiKQ0KI2dnX2NpcmNfdmljdG9yaWFzDQojbGFzIHNpZ3VpZW50ZXMgbGluZWFzIGRlIGNvZGlnbyBzZSB1dGlsaXphbiBwYXJhIGVsaW1pbmFyIGxvcyBib3JkZXMgYmxhbmNvcw0KZ2dzYXZlKCIuL3Bsb3RzL2dnX2NpcmNfdmljdG9yaWFzLnBuZyIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNSkNCmBgYA0KDQo8Y2VudGVyPg0KDQoNCiFbQ2FtcGVvbmVzIGRlbCBtdW5kb10oLi9wbG90cy9nZ19jaXJjX3ZpY3Rvcmlhcy5wbmcpe3dpZHRoPTgwMCBoZWlnaHQ9NjAwfQ0KDQoNCjwvY2VudGVyPg0KDQoNCiMjIDMuMyBUZW1wb3JhZGEgMjAyMQ0KDQojIyMgQ2FtcGXDs24gZGVsIG11bmRvey50YWJzZXR9DQoNCkVsIHBhc2FkbyBmaW4gZGUgc2VtYW5hIGVsIHBpbG90byBob2xhbmTDqXMgZGUgMjQgYcOxb3MgTWF4IFZlcnN0YXBwZW4sIHNlIGRlY2xhcmFiYSBjYW1wZcOzbiBkZSBsYSB0ZW1wb3JhZGEgMjAyMSBkZSBGb3JtdWxhIDEuRXN0ZSwgY29uc2lndWnDsyBzdSBncmFuIHRyaXVuZm8sIHRyYXMgdW5hIGR1cmEgbHVjaGEgY29udHJhIGVsIHBpbG90byBpbmdsw6lzIExld2lzIEhhbWlsdG9uIGR1cmFudGUgdG9kYSBsYSB0ZW1wb3JhZGEsIGxsZWdhbmRvIGFtYm9zIGEgbGEgw7psdGltYSBjYXJyZXJhIGRlbCBjYW1wZW9uYXRvIGVtcGF0YWRvcyBhIHB1bnRvcywgYWxnbyBxdWUgc29sYW1lbnRlIGhhYsOtYSBzdWNlZGlkbyB1bmEgdmV6IGVuIGxhIGhpc3RvcmlhLg0KDQojIyMjIFZlcnN0YXBwZW4NCg0KPGNlbnRlcj4NCiFbVmVyc3RhcHBlbiAtIE51ZXZvIENhbXBlw7NuIDIwMjFdKC4vaW1hZ2VuZXMvQ0FNUEVPTi9jYW1wZW9uX3ZlcnN0YXBwZW4uanBnKXt3aWR0aD02NDAgaGVpZ2h0PTgwMH0NCjwvY2VudGVyPg0KDQojIyMjIEZpbmFsIGRlIGluZmFydG8NCg0KRWwgZmluZGUgc2VtYW5hLCBjb21lbnphYmEgYmllbiBwYXJhIGVsIHBpbG90byBob2xhbmTDqXMsIHlhIHF1ZSBlbCBzw6FiYWRvIHNlIGFsesOzIGNvbiBsYSBwb2xlLCBzYWxpZW5kbyBhc8OtIGVuIGVsIHByaW1lciBwdWVzdG8gZGUgbGEgY2FycmVyYS4gUGVybyB0b2RvIHNlIGNvbWVuesOzIGEgdG9yY2VyIGN1YW5kbyBIYW1pbHRvbiBsZSBhZGVsYW50byBlbiBsYSBzYWxpZGEsIHkgVmVyc3RhcHBlbiBubyBwb2TDrWEgYWxjYW56YXJsby4gRWwgcGlsb3RvIGluZ2zDqXMgcmVpbsOzIGxhIGNhcnJlcmEgZHVyYW50ZSA1MyB2dWVsdGFzIGRlIDU2IHF1ZSB0ZW7DrWEgZWwgZ3JhbiBQcmVtaW8gZGUgWWFzIE1hcmluYS4gVG9kbyBwYXJlY8OtYSBhcHVudGFyIGEgcXVlIEhhbWlsdG9uIGliYSBhIGNvbnNlZ3VpciBzdSBvY3Rhdm8gY2FtcGVvbmF0byBkZWwgbXVuZG8sIHBlcm8gZW4gZXN0YSB2dWVsdGEgNTMsIGVsIHBpbG90byBjYW5hZGllbnNlIExhdGlmaSBzdWZyacOzIHVuIGFjY2lkZW50ZSBxdWUgcHJvdm9jw7MgbGEgc2FsaWRhIGRlbCBzYWZldHkgY2FyLCAgeSBwb3IgdGFudG8gdG9kb3MgbG9zIGNvY2hlcyBzZSBpYmFuIGEgdm9sdmVyIGEganVudGFyIHVub3MgZGV0csOhcyBkZSBvdHJvcyByZWR1Y2llbmRvIHN1cyBkaXN0YW5jaWFzLCBhcHJvdmVjaGFuZG8gZWwgZXF1aXBvIFJlZCBCdWxsIHBhcmEgZW4gdW5hIGdyYW4ganVnYWRhIGRlIGVzdHJhdGVnaWEgZW50cmFyIGEgYm94ZXMgcGFyYSBtb250YXIgZWwgbmV1bcOhdGljbyBibGFuZG8sIHkgdHJhcyBsYSBzYWxpZGEgZGVsIHNhZmV0eSBjYXIsIGVsIGpvdmVuIHBpbG90byBob2xhbmTDqXMgY29uc2lndWnDsyBhZGVsYW50YXIgZW4gbGEgw7psdGltYSB2dWVsdGEgZGVsIGNhbXBlb25hdG8gYSBMZXdpcyBIYW1pbHRvbiwgeSBhc8OtIGFsemFyc2UgY29uIGVsIHTDrXR1bG8gZGUgdW5hIGRlIGxhcyB0ZW1wb3JhZGFzIG3DoXMgZW1vY2lvbmFudGVzIGRlIGxhIEYxLg0KDQpgYGB7cn0NCg0Kc2FsaWRhIDwtIGltYWdlX3JlYWQoIi4vaW1hZ2VuZXMvQ0FNUEVPTi9oYW1pbHRvbl9hZGVsLmpwZyIpICU+JSBpbWFnZV9zY2FsZSguLCAiNTAwIiklPiUgIGltYWdlX2Fubm90YXRlKC4sICJIYW1pbHRvbiBzZSBwb25lIHBvciBkZWxhbnRlIiwgc2l6ZSA9IDIwLCBncmF2aXR5ID0gIm5vcnRod2VzdCIsIGNvbG9yID0gImN5YW4iLCBib3hjb2xvciA9ICJncmF5MTMiKQ0KbGF0aWZpIDwtIGltYWdlX3JlYWQoIi4vaW1hZ2VuZXMvQ0FNUEVPTi9sYXRpZmkuanBnIikgJT4lIGltYWdlX3NjYWxlKC4sICI1MDAiKSU+JSAgaW1hZ2VfYW5ub3RhdGUoLiwgIkFjY2lkZW50ZSBkZSBMYXRpZmkiLCBzaXplID0gNDAsIGdyYXZpdHkgPSAibm9ydGh3ZXN0IiwgY29sb3IgPSAiY3lhbiIsIGJveGNvbG9yID0gImdyYXkxMyIpDQpzYWZldHkgPC0gaW1hZ2VfcmVhZCgiLi9pbWFnZW5lcy9DQU1QRU9OL3NhZmV0eS5qcGciKSAlPiUgaW1hZ2Vfc2NhbGUoLiwgIjUwMCIpJT4lICBpbWFnZV9hbm5vdGF0ZSguLCAiU2FsZSBlbCBzYWZldHkgY2FyIiwgc2l6ZSA9IDQwLCBncmF2aXR5ID0gIm5vcnRod2VzdCIsIGNvbG9yID0gImN5YW4iLCBib3hjb2xvciA9ICJncmF5MTMiKQ0KcnVlZGFfYV9ydWVkYSA8LSBpbWFnZV9yZWFkKCIuL2ltYWdlbmVzL0NBTVBFT04vcnVlZGFhcnVlZGEuanBlZyIpICU+JSBpbWFnZV9zY2FsZSguLCAiNTAwIiklPiUgIGltYWdlX2Fubm90YXRlKC4sICJJZ3VhbGRhZCBtw6F4aW1hIiwgc2l6ZSA9IDMwLCBncmF2aXR5ID0gIm5vcnRod2VzdCIsIGNvbG9yID0gImN5YW4iLCBib3hjb2xvciA9ICJncmF5MTMiKQ0KbWV0YSA8LSBpbWFnZV9yZWFkKCIuL2ltYWdlbmVzL0NBTVBFT04vdmVyc3RhcHBlbl9nYW5hLmpwZyIpICU+JSBpbWFnZV9zY2FsZSguLCAiNTAwIiklPiUgIGltYWdlX2Fubm90YXRlKC4sICJWZXJzdGFwcGVuIHNlIGhhY2UgY29uIGxhIHZpY3RvcmlhIiwgc2l6ZSA9IDIwLCBncmF2aXR5ID0gIm5vcnRod2VzdCIsIGNvbG9yID0gImN5YW4iLCBib3hjb2xvciA9ICJncmF5MTMiKQ0KdHJvZmVvIDwtIGltYWdlX3JlYWQoIi4vaW1hZ2VuZXMvQ0FNUEVPTi9jYW1wZW9uX3Ryb2Zlby5qcGciKSAlPiUgaW1hZ2Vfc2NhbGUoLiwgIjUwMCIpJT4lICBpbWFnZV9hbm5vdGF0ZSguLCAiTnVldm8gY2FtcGXDs24gZGVsIG11bmRvIiwgc2l6ZSA9IDMwLCBncmF2aXR5ID0gIm5vcnRod2VzdCIsIGNvbG9yID0gImN5YW4iLCBib3hjb2xvciA9ICJncmF5MTMiKQ0KbGFzdF9yYWNlIDwtIGMoc2FsaWRhLCBsYXRpZmksIHNhZmV0eSwgcnVlZGFfYV9ydWVkYSwgbWV0YSwgdHJvZmVvKQ0KDQppbWFnZV9hbmltYXRlKGltYWdlX3NjYWxlKGxhc3RfcmFjZSksIGZwcyA9IDAuNSkNCmBgYA0KDQojIyMjIFZlcnN0YXBwZW4gdnMgSGFtaWx0b24NCg0KRW4gbGEgc2lndWllbnRlIHRhYmxhIHB1ZWRlIG9ic2VydmFyc2UgbGEgaWd1YWxkYWQgcXVlIGhhIGV4aXN0aW8gZW50cmUgbG9zIGRvcyBwaWxvdG9zIGEgbG8gbGFyZ28gZGVsIGNhbXBlb25hdG8gZGVsIG11bmRvLCBsbGVnYW5kbyBpbmNsdXNvIGVtcGF0YWRvcyBhIHB1bnRvcyBhIGxhIMO6bHRpbWEgY2FycmVyYS4NCg0KYGBge3J9DQp2ZXJzX3ZzX2hhbSA8LSBkYXRhLmZyYW1lKA0KICAibm9tYnJlIiA9IGMoIk1heCBWZXJzdGFwcGVuIiwgIkxld2lzIEhhbWlsdG9uIiksDQogICJwaWxvdG8iID0gYygiLi9pbWFnZW5lcy9waWxvdG9zL3ZlcnN0YXBwZW4uanBnIiwiLi9pbWFnZW5lcy9waWxvdG9zL2hhbWlsdG9uLnBuZyIpLA0KICAicGFpcyIgPSBjKCIuL2ltYWdlbmVzL3BhaXNlcy9ob2xhbmRhLnBuZyIsICIuL2ltYWdlbmVzL3BhaXNlcy91ay5wbmciKSwNCiAgImVzY3VkZXJpYSIgPSBjKCIuL2ltYWdlbmVzL2VzY3VkZXJpYXMvcmVkYnVsbC5wbmciLCAiLi9pbWFnZW5lcy9lc2N1ZGVyaWFzL21lcmNlZGVzLnBuZyIpLA0KICAicHVudG9zIiA9IGMoMzk1LjUsIDM4Ny41KSwNCiAgInZpY3RvcmlhcyIgPSBjKDEwLCA4KSwNCiAgInBvZGl1bXMiID0gYygxOCwgMTcpLA0KICAicG9sZXMiID0gYygxMCwgNSksDQogICJ2dWVsdGFzX3JhcGlkYXMiID0gYyg2LCA2KSkNCiAgDQoNCiANCnRhYmxhX3Zlcl9oYW0gPC0gdmVyc192c19oYW0gJT4lIGd0KCkgJT4lIA0KICB0ZXh0X3RyYW5zZm9ybSggbG9jYXRpb25zID0gY2VsbHNfYm9keShjb2x1bW5zID0gYyhwaWxvdG8pKSwgZm4gPSBmdW5jdGlvbih4KSB7Z3Q6OmxvY2FsX2ltYWdlKHgsIGhlaWdodCA9IDgwKX0pICU+JSANCiAgdGV4dF90cmFuc2Zvcm0oIGxvY2F0aW9ucyA9IGNlbGxzX2JvZHkoY29sdW1ucyA9IGMocGFpcykpLCBmbiA9IGZ1bmN0aW9uKHgpIHtndDo6bG9jYWxfaW1hZ2UoeCwgaGVpZ2h0ID0gNjApfSkgJT4lICANCiAgdGV4dF90cmFuc2Zvcm0oIGxvY2F0aW9ucyA9IGNlbGxzX2JvZHkoY29sdW1ucyA9IGMoZXNjdWRlcmlhKSksIGZuID0gZnVuY3Rpb24oeCkge2d0Ojpsb2NhbF9pbWFnZSh4LCBoZWlnaHQgPSA4MCl9KSAlPiUgDQogIHRhYl9oZWFkZXIodGl0bGUgPSBtZCgiKipWZXJzdGFwcGVuIHZzIEhhbWlsdG9uKioiKSwgc3VidGl0bGUgPSBtZCgiMjAyMSIpKSAlPiUgICBjb2xzX2xhYmVsKA0KICAgIG5vbWJyZSA9IGh0bWwoIiIpLA0KICAgIHBpbG90byA9IGh0bWwoIiIpLA0KICAgIHBhaXMgPSBodG1sKCIiKSwNCiAgICBlc2N1ZGVyaWEgPSBodG1sKCJFc2N1ZGVyw61hIiksDQogICAgcHVudG9zID0gaHRtbCgiUHVudG9zIiksDQogICAgdmljdG9yaWFzID0gaHRtbCgiVmljdG9yaWFzIiksDQogICAgcG9kaXVtcyA9IGh0bWwoIlBvZGl1bXMiKSwNCiAgICBwb2xlcyA9IGh0bWwoIlBvbGVzIiksDQogICAgdnVlbHRhc19yYXBpZGFzID0gaHRtbCgiVnVlbHRhcyByw6FwaWRhcyIpKSAlPiUgIA0KICB0YWJfb3B0aW9ucyh0YWJsZS5iYWNrZ3JvdW5kLmNvbG9yID0gImdyYXkxMyIsICAgdGFibGUuZm9udC5jb2xvci5saWdodCA9ICJjeWFuIikgJT4lIA0KICBjb2xzX2FsaWduKGFsaWduID0gImNlbnRlciIsDQogIGNvbHVtbnMgPSBldmVyeXRoaW5nKCkpDQoNCg0KdGFibGFfdmVyX2hhbQ0KYGBgDQoNCg0KIyMjIFBhcnJpbGxhIGRlIHBpbG90b3MgDQoNCkEgY29udGludWFjacOzbiwgcHVlZGUgdmVyc2UgbG8gcXVlIGhhIHNpZG8gbGEgcGFycmlsbGEgZGUgcGlsb3RvcyBkdXJhbnRlIGVzdGEgdGVtcG9yYWRhLCBhw7FhZGllbmRvIGFsIGhpc3TDs3JpY28gcGlsb3RvIFJvYmVydCBLw7piaWNhLCBxdWUgdHV2byBxdWUgc3VzdHV0dWlyIGEgUsOkaWtrw7ZuZW4gZHVyYW50ZSB1biBncmFuIHByZW1pby4NCg0KYGBge3J9DQoNCnBpbG90b3NfMjAyMSA8LSBmdWxsX2pvaW4oY2FycmVyYXMsIHJlc3VsdGFkb3MsIGMoInJhY2VJZCIgPSAicmFjZUlkIikgKSAlPiUgDQogIGZ1bGxfam9pbiguLHBpbG90b3MsIGMoImRyaXZlcklkIj0iZHJpdmVySWQiKSkgJT4lIA0KICBmaWx0ZXIoeWVhcj09IjIwMjEiKSAlPiUgDQogIHNlbGVjdChmb3JlbmFtZSxzdXJuYW1lLCB5ZWFyKSAlPiUgZGlzdGluY3QoZm9yZW5hbWUsc3VybmFtZSkgJT4lIG5hLm9taXQoKSAlPiUgYXJyYW5nZShzdXJuYW1lKSAlPiUgc3RyX3JlcGxhY2VfYWxsKC4sICLDg8KpIiwgIsOpIikgJT4lIHN0cl9yZXBsYWNlX2FsbCguLCAiw4PCpCIsICLDpCIpICU+JSBzdHJfcmVwbGFjZV9hbGwoLiwgIsODwrYiLCAiw7YiKQ0KDQpub21icmVzX25vcm1hbGVzIDwtIGMoIkFsb25zbyIsICJCb3R0YXMiLCAiR2FzbHkiLCAiR2lvdmluYXp6aSIsICJIYW1pbHRvbiIsICJMYXRpZmkiLCAiTGVjbGVyYyIsICJNYXplcGluIiwgIk5vcnJpcyIsICJPY29uIiwgIlDDqXJleiIsICJSw6Rpa2vDtm5lbiIsICJSaWNjaWFyZG8iLCAiUnVzc2VsbCIsICJTYWlueiIsICJTY2h1bWFjaGVyIiwgIlN0cm9sbCIsICJUc3Vub2RhIiwgIlZlcnN0YXBwZW4iLCAiVmV0dGVsIikNCg0KcGlsb3Rvc18yMDIxIDwtICBmdWxsX2pvaW4oY2FycmVyYXMsIHJlc3VsdGFkb3MsIGMoInJhY2VJZCIgPSAicmFjZUlkIikgKSAlPiUgDQogIGZ1bGxfam9pbiguLHBpbG90b3MsIGMoImRyaXZlcklkIj0iZHJpdmVySWQiKSkgJT4lIA0KICBmaWx0ZXIoeWVhcj09IjIwMjEiKSAlPiUgDQogIHNlbGVjdChmb3JlbmFtZSxzdXJuYW1lLCB5ZWFyKSAlPiUgZGlzdGluY3QoZm9yZW5hbWUsc3VybmFtZSkgJT4lIG5hLm9taXQoKSAlPiUgYXJyYW5nZShzdXJuYW1lKSAlPiUgYWRkX2NvbHVtbihub21icmVzX25vcm1hbGVzKSAgDQogDQoNCiMgUMODwqlyZXoNCiMgUsODwqRpa2vDg8K2bmVuDQpmb3Rvc19waWxfMjAyMSA8LSBjKCIuL2ltYWdlbmVzL3BpbG90b3MvYWxvbnNvLnBuZyIsICIuL2ltYWdlbmVzL3BpbG90b3MvYm90dGFzLnBuZyIsICIuL2ltYWdlbmVzL3BpbG90b3MvZ2FzbHkucG5nIiwgIi4vaW1hZ2VuZXMvcGlsb3Rvcy9naW92aW5henppLmpwZyIsICIuL2ltYWdlbmVzL3BpbG90b3MvaGFtaWx0b24ucG5nIiwgIi4vaW1hZ2VuZXMvcGlsb3Rvcy9sYXRpZmkucG5nIiwgIi4vaW1hZ2VuZXMvcGlsb3Rvcy9sZWNsZXJjLnBuZyIsICIuL2ltYWdlbmVzL3BpbG90b3MvbWF6ZXBpbi5wbmciLCAiLi9pbWFnZW5lcy9waWxvdG9zL25vcnJpcy5wbmciLCAiLi9pbWFnZW5lcy9waWxvdG9zL29jb24uanBnIiwgIi4vaW1hZ2VuZXMvcGlsb3Rvcy9wZXJlei5wbmciLCAiLi9pbWFnZW5lcy9waWxvdG9zL3JhaWtrb25lbi5wbmciLCAiLi9pbWFnZW5lcy9waWxvdG9zL3JpY2NpYXJkby5wbmciLCAiLi9pbWFnZW5lcy9waWxvdG9zL3J1c3NlbGwucG5nIiwgIi4vaW1hZ2VuZXMvcGlsb3Rvcy9zYWluei5wbmciLCAiLi9pbWFnZW5lcy9waWxvdG9zL21pY2sucG5nIiwgIi4vaW1hZ2VuZXMvcGlsb3Rvcy9zdHJvbGwucG5nIiwgIi4vaW1hZ2VuZXMvcGlsb3Rvcy90c3Vub2RhLnBuZyIsICIuL2ltYWdlbmVzL3BpbG90b3MvdmVyc3RhcHBlbi5qcGciLCAiLi9pbWFnZW5lcy9waWxvdG9zL3ZldHRlbC5wbmciKQ0KDQpmb3Rvc19wYWlzXzIwMjEgPC0gYygiLi9pbWFnZW5lcy9wYWlzZXMvZXNwYW55YS5wbmciLCAiLi9pbWFnZW5lcy9wYWlzZXMvZmlubGFuZGlhLnBuZyIsICIuL2ltYWdlbmVzL3BhaXNlcy9mcmFuY2lhLnBuZyIsICIuL2ltYWdlbmVzL3BhaXNlcy9pdGFsaWEucG5nIiwiLi9pbWFnZW5lcy9wYWlzZXMvdWsucG5nIiwgIi4vaW1hZ2VuZXMvcGFpc2VzL2NhbmFkYS5wbmciLCIuL2ltYWdlbmVzL3BhaXNlcy9tb25hY28ucG5nIiwgIi4vaW1hZ2VuZXMvcGFpc2VzL3J1c2lhLnBuZyIsIi4vaW1hZ2VuZXMvcGFpc2VzL3VrLnBuZyIsICIuL2ltYWdlbmVzL3BhaXNlcy9mcmFuY2lhLnBuZyIsIi4vaW1hZ2VuZXMvcGFpc2VzL21leGljby5wbmciLCAiLi9pbWFnZW5lcy9wYWlzZXMvZmlubGFuZGlhLnBuZyIsIi4vaW1hZ2VuZXMvcGFpc2VzL2F1c3RyYWxpYS5wbmciLCAiLi9pbWFnZW5lcy9wYWlzZXMvdWsucG5nIiwiLi9pbWFnZW5lcy9wYWlzZXMvZXNwYW55YS5wbmciLCAiLi9pbWFnZW5lcy9wYWlzZXMvYWxlbWFuaWEucG5nIiwiLi9pbWFnZW5lcy9wYWlzZXMvY2FuYWRhLnBuZyIsICIuL2ltYWdlbmVzL3BhaXNlcy9qYXBvbi5wbmciLCIuL2ltYWdlbmVzL3BhaXNlcy9ob2xhbmRhLnBuZyIsICIuL2ltYWdlbmVzL3BhaXNlcy9hbGVtYW5pYS5wbmciKQ0KDQpmb3Rvc19lc2NfMjAyMSA8LSBjKCIuL2ltYWdlbmVzL2VzY3VkZXJpYXMvYWxwaW5lLnBuZyIsIi4vaW1hZ2VuZXMvZXNjdWRlcmlhcy9tZXJjZWRlcy5wbmciLCIuL2ltYWdlbmVzL2VzY3VkZXJpYXMvYWxwaGF0YXVyaS5wbmciLCAiLi9pbWFnZW5lcy9lc2N1ZGVyaWFzL2FsZmFyb21lby5qcGciLCIuL2ltYWdlbmVzL2VzY3VkZXJpYXMvbWVyY2VkZXMucG5nIiwgIi4vaW1hZ2VuZXMvZXNjdWRlcmlhcy93aWxsaWFtcy5wbmciLCIuL2ltYWdlbmVzL2VzY3VkZXJpYXMvZmVycmFyaS5wbmciLCAiLi9pbWFnZW5lcy9lc2N1ZGVyaWFzL2hhYXMucG5nIiwiLi9pbWFnZW5lcy9lc2N1ZGVyaWFzL21jbGFyZW4ucG5nIiwgIi4vaW1hZ2VuZXMvZXNjdWRlcmlhcy9hbHBpbmUucG5nIiwiLi9pbWFnZW5lcy9lc2N1ZGVyaWFzL3JlZGJ1bGwucG5nIiwgIi4vaW1hZ2VuZXMvZXNjdWRlcmlhcy9hbGZhcm9tZW8uanBnIiwiLi9pbWFnZW5lcy9lc2N1ZGVyaWFzL21jbGFyZW4ucG5nIiwgIi4vaW1hZ2VuZXMvZXNjdWRlcmlhcy93aWxsaWFtcy5wbmciLCIuL2ltYWdlbmVzL2VzY3VkZXJpYXMvZmVycmFyaS5wbmciLCAiLi9pbWFnZW5lcy9lc2N1ZGVyaWFzL2hhYXMucG5nIiwiLi9pbWFnZW5lcy9lc2N1ZGVyaWFzL2FzdG9uLnBuZyIsICIuL2ltYWdlbmVzL2VzY3VkZXJpYXMvYWxwaGF0YXVyaS5wbmciLCIuL2ltYWdlbmVzL2VzY3VkZXJpYXMvcmVkYnVsbC5wbmciLCAiLi9pbWFnZW5lcy9lc2N1ZGVyaWFzL2FzdG9uLnBuZyIpDQoNCnBpbG90b3NfMjAyMSA8LSBwaWxvdG9zXzIwMjEgJT4lDQogIGFkZF9jb2x1bW4oZm90b3NfcGlsXzIwMjEsIGZvdG9zX3BhaXNfMjAyMSwgZm90b3NfZXNjXzIwMjEpICU+JSBzZWxlY3Qobm9tYnJlc19ub3JtYWxlcywgZm90b3NfcGlsXzIwMjEsIGZvdG9zX3BhaXNfMjAyMSwgZm90b3NfZXNjXzIwMjEpDQoNCg0KbXVuZGlhbF8yMDIxIDwtIHBpbG90b3NfMjAyMSAlPiUgZ3QoKSAlPiUgdGV4dF90cmFuc2Zvcm0oIGxvY2F0aW9ucyA9IGNlbGxzX2JvZHkoY29sdW1ucyA9IGMoZm90b3NfcGlsXzIwMjEpKSwgZm4gPSBmdW5jdGlvbih4KSB7Z3Q6OmxvY2FsX2ltYWdlKHgsIGhlaWdodCA9IDEwMCl9KSAlPiUgdGV4dF90cmFuc2Zvcm0oIGxvY2F0aW9ucyA9IGNlbGxzX2JvZHkoY29sdW1ucyA9IGMoZm90b3NfcGFpc18yMDIxKSksIGZuID0gZnVuY3Rpb24oeCkge2d0Ojpsb2NhbF9pbWFnZSh4LCBoZWlnaHQgPSA1MCl9KSAlPiUgdGV4dF90cmFuc2Zvcm0oIGxvY2F0aW9ucyA9IGNlbGxzX2JvZHkoY29sdW1ucyA9IGMoZm90b3NfZXNjXzIwMjEpKSwgZm4gPSBmdW5jdGlvbih4KSB7Z3Q6OmxvY2FsX2ltYWdlKHgsIGhlaWdodCA9IDcwKX0pICU+JSB0YWJfaGVhZGVyKHRpdGxlID0gbWQoIioqUGlsb3RvcyAyMDIxKioiKSwgc3VidGl0bGUgPSBtZCgiUGFycmlsbGEiKSkgJT4lICAgY29sc19sYWJlbCgNCiAgICBub21icmVzX25vcm1hbGVzID0gaHRtbCgiIiksDQogICAgZm90b3NfcGlsXzIwMjEgPSBodG1sKCIiKSwNCiAgICBmb3Rvc19wYWlzXzIwMjEgPSBodG1sKCIiKSwNCiAgICBmb3Rvc19lc2NfMjAyMSA9IGh0bWwoIiIpKSAlPiUgIA0KICB0YWJfb3B0aW9ucyh0YWJsZS5iYWNrZ3JvdW5kLmNvbG9yID0gImdyYXkxMyIsICAgdGFibGUuZm9udC5jb2xvci5saWdodCA9ICJjeWFuIikgJT4lIA0KICBjb2xzX2FsaWduKGFsaWduID0gImNlbnRlciIsDQogIGNvbHVtbnMgPSBldmVyeXRoaW5nKCkpDQoNCg0KbXVuZGlhbF8yMDIxDQpgYGANCg0KTGEgcGFycmlsbGEgZGUgcGlsb3RvcyBkZSBlc3RhIHRlbXBvcmFkYSAyMDIxLCB2YSBhIHN1ZnJpciB1bmEgc2VyaWUgZGUgY2FtYmlvcyByZXNwZWN0byBhIGxhIHRlbXBvcmFkYSBkZSAyMDIyLiBWYWx0ZXJpIEJvdHRhcyBhYmFuZG9uYSBNZXJjZWRlcyB5IG9jdXBhIHVuIGFzaWVudG8gZW4gQWxmYSBSb21lby4gRXN0ZSBzZXLDoSBzdXN0aXR1aWRvIGVuIE1lcmNlZGVzIHBvciBlbCBwaWxvdG8gaW5nbMOpcyBkZSBXaWxsaWFtcywgR2VvcmdlIFJ1c3NlbCwgcXVlIGEgc3UgdmV6IGNlZGUgc3UgaHVlY28gYWwgZXgtIHBpbG90byBkZSBSZWQgQnVsbCBBbGV4IEFsYm9uLiBDb21vIGxvcyBwaWxvdG9zIEtpbWkgUsOkaWtrw7ZuZW4geSBBbnRvbmlvIEdpb3ZpbmF6emkgYWJhbmRvbmFuIGxhIEYxLCBzdXMgcHVlc3RvcyBlbiBlbCBlcXVpcG8gQWxmYSBSb21lbywgc2Vyw6FuIG9jdXBhZG9zIHBvciBWYWx0ZXJpIEJvdHRhcywgY29tbyBoZSBtZW5jaW9uYWRvIGFudGVyaW9ybWVudGUgeSBwb3IgIEd1YW55dSBaaG91IHF1ZSBzZXLDoSBzdSBjb21wYcOxZXJvLiBFbCBwaWxvdG8gY2hpbm8sIHF1ZSBoYSBkaXNwdXRhZG8gZXN0YSB0ZW1wb3JhZGEgIGVsIGNhbXBlb25hdG8gZGVsIG11bmRvIGRlIEbDs3JtdWxhIDIsIHByb2NlZGUgZGUgbGEgYWNhZGVtaWEgZGUgQWxwaW5lLg0KDQojIyMgVGVtcGxvcw0KDQpFbCBzaWd1aWVudGUgZ2xvYm8gdGVycmFxdWVvIG11ZXN0cmEgdG9kb3MgbG9zIGdyYW5kZXMgcHJlbWlvcyAgZGUgZXN0YSB0ZW1wb3JhZGEsIHNpdHVhbmRvbG9zIGUgaW5kaWNhbmRvIGxhIHJvbmRhIGRlbCBtdW5kaWFsIHF1ZSBzb24geSBlbCBwYcOtcyBkb25kZSBzZSBoYW4gY2VsZWJyYWRvLiANCg0KYGBge3IsIGV2YWwgPSBUUlVFLCBlY2hvID0gVFJVRX0NCg0KZ2xvYm9fY2lyYyA8LWNyZWF0ZV9nbG9iZSgpICU+JSBnbG9iZV9wb3YoNDUuNjE1NjAsIDkuMjgxMTEwKSAlPiUgZ2xvYmVfYmFycyhjb29yZHMobGF0LCBsbmcsIGxhYmVsICA9IHZhcmlhYmxlcywgY29sb3IgPSByb3VuZDIpLCBkYXRhID0gY2FycmVyYXNfMjFfdjIpICAlPiUgc2NhbGVfYmFyc19jb2xvcigpDQpnbG9ib19jaXJjDQpgYGANCg0KDQoNCiMjIDMuNCBFbCBuYW5vDQoNCkZlcm5hbmRvIEFsb25zbyBEw61heiAoT3ZpZWRvLCBBc3R1cmlhczsgMjkgZGUganVsaW8gZGUgMTk4MSkgZXMgdW4gcGlsb3RvIGVzcGHDsW9sIGRlIGF1dG9tb3ZpbGlzbW8gZGUgdmVsb2NpZGFkLiBDb24gZG9zIHTDrXR1bG9zIG11bmRpYWxlcyBlbiBzdSBwYWxtYXLDqXMgKFJlbmF1bHQgMjAwNSB5IDIwMDYpLCBkaWZlcmVudGVzIGVzdHVkaW9zIHByZWRpY3Rpdm9zIGNvbG9jYW4gYSBBbG9uc28gZW50cmUgbG9zIG1lam9yZXMgcGlsb3RvcyBkZSBsYSBoaXN0b3JpYS4gUG9kw61hIGhhYmVyIGdhbmFkbyBtdWNobyBtw6FzLCBwZXJvIGVuIG9jYXNpb25lcyBsYSBlbGVjY2nDs24gZGVsIGVxdWlwbyBubyBhY29tcGHDscOzIGEgc3UgYW1iaWNpw7NuLg0KDQojIyMgQWxvbnNvIHZzIGNvbXBhw7Flcm9zIGRlIGVxdWlwbw0KDQpBbG9uc28gaGEgdGVuaWRvIDEyIGNvbXBhw7Flcm9zIGR1cmFudGUgc3VzIDE3IHRlbXBvcmFkYXMuIEVsIHBpbG90byBhc3R1cmlhbm8gZW4gdG9kb3MgZXN0b3MgYcOxb3MsIHNvbG8gaGEgcXVlZGFkbyB1bmEgdmV6IHBvciBkZXRyw6FzIGRlIHN1IGNvbXBhw7Flcm8sIHkgZnVlIGVuIDIwMTUgY29uIEJ1dHRvbiwgZHVyYW50ZSBsYSB0ZW1wb3JhZGEgaG9ycmlibGUgcXVlIGxsZXZvIGEgY2FibyBsYSBlc2N1ZGVyw61hIE1jTGFyZW4uIEVuIDIwMDEgY29uIE1hcnF1ZXMgeSBlbiAyMDA3IGNvbiBIYW1pbHRvbiBxdWVkw7MgIGVtcGF0YWRvIGEgcHVudG9zIChlbiBlbCBjYXNvIGRlIE1hcnF1ZXMgbmluZ3VubyBwdW50w7phKSwgYXVucXVlIGFtYm9zIHRlcm1pbmFuIHBvciBkZWxhbnRlIGVuIGxhIGNsYXNpZmljYWNpw7NuIHBvciBtZWpvciBwdWVzdG8gZmluYWwgZW4gY2FycmVyYS4gVGllbmUgMjMyIG1lam9yZXMgcHVlc3RvcyBlbiBjYXJyZXJhIHBvciA2MyBwZW9yZXMuIFVub3MgbsO6bWVyb3MgcXVlIG5vIHNvbiBhbGNhbnphZG9zIG5pIHBvciBsb3MgbWVqb3JlcyBwaWxvdG9zIGRlIGxhIGhpc3RvcmlhLiANCg0KYGBge3IsIGV2YWwgPSBUUlVFLCBlY2hvID0gVFJVRX0NCmdjKCkgDQpnZ2Fsb192c19hbGwgPC0gZ2dwbG90KGRhdGEgPSBBTE9fVlNfQUxMLCBhZXMocm91bmQsIHB1bnRvc19hY3VtdWxhZG9zLCBjb2xvciA9IGRyaXZlclJlZikpICsNCiAgZ2VvbV9saW5lKCkgKw0KICBnZW9tX3BvaW50KCkgKyANCiAgbGFicyh0aXRsZSA9ICJBbG9uc28gY29udHJhIGVsIG11bmRvIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJBbG9uc28gVlMgY2FkYSBjb21wYcOxZXJvIGRlIGVxdWlwbyIsDQogICAgICAgeSA9ICJQdW50b3MiLCB4ID0gIiIpICsgdGhlbWUoYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmF5MzAiLA0KICAgIGxpbmV0eXBlID0gInNvbGlkIiksIGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXkzMCIpLA0KICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXkyMCIpLA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAiYmxhbmsiKSwNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSwNCiAgICAgICAgY29sb3VyID0gIndoaXRlIiksIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAid2hpdGUiKSwNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCwNCiAgICAgICAgY29sb3VyID0gIndoaXRlIiwgaGp1c3QgPSAwLjUpLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAid2hpdGUiKSwNCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3VyID0gIndoaXRlIiksDQogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIsDQogICAgICAgIGNvbG91ciA9ICJncmF5MTMiLCBsaW5ldHlwZSA9ICJzb2xpZCIpLA0KICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIsDQogICAgICAgIGNvbG91ciA9ICJncmF5MTMiLCBsaW5ldHlwZSA9ICJzb2xpZCIpLA0KICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiLA0KICAgICAgICBjb2xvdXIgPSAiZ3JheTEzIiksIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTEzIiwNCiAgICAgICAgY29sb3VyID0gImdyYXkxMyIpKSArbGFicyh4ID0gIk7CuiBjYXJyZXJhIiwgY29sb3VyID0gIlBpbG90byIpICsgdGhlbWUocGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsDQogICAgaGp1c3QgPSAwLjUpKSArIGZhY2V0X3dyYXAoIH4geWVhcikgIysgdHJhbnNpdGlvbl9yZXZlYWwocm91bmQpDQoNCmdnYWxvX3ZzX2FsbA0KDQpgYGANCg0KIyMjIEFsb25zbyB2cyBIYW1pbHRvbg0KDQpMYSByaXZhbGlkYWQgZW50cmUgZXN0b3MgbG9zIGRvcyBwbG90b3MsIG3DoXMgcXVlIGNvbm9jaWRhLHB1ZWRlICBvYnNlcnZhcnNlIGVuIGxhIHRhYmxhIHF1ZSBzZSBkZWNhbnRhIHBhcmEgZWwgbGFkbyBkZSBIYW5pbHRvbiwgeWEgcXVlIGVzdGUgdGllbmUgbcOhcyBjYW1wZW9uYXRvcyB5IG3DoXMgcHVudG9zLCBwZXJvIG5vIHNpZ25pZmljYSBuaSBtdWNobyBtZW5vcyBxdWUgc2VhIG1lam9yIHBpbG90by4gIA0KDQpGZXJuYW5kbyBBbG9uc28geSBMZXdpcyBIYW1pbHRvbiBsbGVnYXJvbiBqdW50b3MgYSBNY0xhcmVuIGVuIDIwMDcuIFVubyBlcmEgYmljYW1wZcOzbiBkZWwgbXVuZG8gZGUgRsOzcm11bGEgMSB0cmFzIHVuYSBldGFwYSBtYXJhdmlsbG9zYSBlbiBSZW5hdWx0LCB5IGVsIG90cm8gdW4gcmVjacOpbiBsbGVnYWRvLCBjb24gZ3JhbiBwcm95ZWNjacOzbi4gU3Ugcml2YWxpZGFkIGRlc2RlIGVudG9uY2VzIGhhIGlkbyBpbmNyZW1lbnRhbmRvLCBkZWJpZG8gYSBkb3MgcGVyc29uYWxpZGFkZXMgbXV5IGZ1ZXJ0ZXMgeSBjb21wZXRpdGl2YXMuDQoNCmBgYHtyLCBldmFsPVRSVUUsIGVjaG89VFJVRX0NCg0KI3NlIG5lY2VzaXRhIHRlbmVyIGNhcmdhZG8gIm5fY2FycmVyYXNfbm9tIiwgInZpY3Rvcmlhc19jb25fbm9tYnJlIg0KIzEyMzQNCg0KYWxvX3ZzX2hhbV90YWJsYSA8LSBhbG9fdnNfaGFtICU+JSBndCgpICU+JSB0ZXh0X3RyYW5zZm9ybSggbG9jYXRpb25zID0gY2VsbHNfYm9keShjb2x1bW5zID0gYyhmb3Rvc19lc3BfaW5nKSksIGZuID0gZnVuY3Rpb24oeCkge2d0Ojpsb2NhbF9pbWFnZSh4LCBoZWlnaHQgPSA1MCl9KSAlPiUgdGV4dF90cmFuc2Zvcm0oIGxvY2F0aW9ucyA9IGNlbGxzX2JvZHkoY29sdW1ucyA9IGMoZm90b3NfQUxPX3ZzX0hBTSkpLCBmbiA9IGZ1bmN0aW9uKHgpIHtndDo6bG9jYWxfaW1hZ2UoeCwgaGVpZ2h0ID0gMTAwKX0pICU+JSB0YWJfaGVhZGVyKHRpdGxlID0gbWQoIioqQWxvbnNvIHZzIEhhbWlsdG9uKioiKSwgc3VidGl0bGUgPSBtZCgiQ29tcGFyYWNpw7NuIikpICU+JSAgIGNvbHNfbGFiZWwoDQogICAgZHJpdmVyUmVmID0gaHRtbCgiIiksDQogICAgbnVtZXJvX2NhcnJlcmFzID0gaHRtbCgiTsK6IGNhcnJlcmFzIiksDQogICAgbl92aWN0b3JpYXMgPSBodG1sKCJOwrogdmljdG9yaWFzIiksDQogICAgZm90b3NfZXNwX2luZyA9IGh0bWwoIlBhw61zIiksDQogICAgZm90b3NfQUxPX3ZzX0hBTSA9IGh0bWwoIiIpKSAlPiUgIA0KICB0YWJfb3B0aW9ucyh0YWJsZS5iYWNrZ3JvdW5kLmNvbG9yID0gImdyYXkxMyIsICAgdGFibGUuZm9udC5jb2xvci5saWdodCA9ICJjeWFuIikgJT4lIA0KICBjb2xzX2FsaWduKGFsaWduID0gImNlbnRlciIsDQogIGNvbHVtbnMgPSBldmVyeXRoaW5nKCkpDQoNCmFsb192c19oYW1fdGFibGENCmBgYA0KDQoNCg0KDQoNCiMgNC4gVHJhYmFqb3MgZW4gbG9zIHF1ZSB0ZSBoYXMgYmFzYWRvDQoNCkNvbiBsb3MgZGF0b3MgcXVlIGhlbW9zIGVuY29udHJhZG8sIGV4aXN0ZW4gdW5hIHNlcmllIGRlIGPDs2RpZ29zIHF1ZSB5YSB0cmFiYWphbiBjb24gZXN0b3MgZGF0b3MsIGVzcGVjaWFsbWVudGUgW2VzdGVdKGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vZWtyZW1iYXlhci9mb3JtdWxhLTEtNzB0aC1hbm5pdmVyc2FyeSksIGEgcGFydGlyIGRlbCBjdWFsLCBzb2JyZSB0b2RvLCBub3MgaGVtb3MgZmlqYWRvIGVuIGxhIGVzdMOpdGljYSBkZSBsb3MgZ3LDoWZpY29zIHkgbGFzIGltYWdlbmVzIGNvbiBsYXMgcXVlIGxvcyBhY29tcGHDsWFiYS4gVGFtYmnDqW4gaGVtb3Mgb2J0ZW5pZG8gaWRlYXMgcGFyYSB0cmFiYWphciBsb3MgZGF0b3MsIHBlcm8gZW4gbWVub3IgbWVkaWRhIHF1ZSBlbCBhcGFydGFkbyB2aXN1YWwsIHlhIHF1ZSBlbCB0cmFiYWpvIGNpdGFkbyBzZSBjZW50cmEgdW5pY2FtZW50ZSBlbiBsYSB0ZW1wb3JhZGEgYWN0dWFsLCBtaWVudHJhcyBxdWUgKipBbHQrIEZvcm11bGEgMSoqIGNvbWJpbmEgdGFudG8gbGEgYWN0dWFsaWRhZCBjb21vIGxhIGhpc3RvcmlhIGVuIGdlbmVyYWwgZGUgbGEgRjEuDQoNCg0KIyA1LiBCaWJsaW9ncmFmw61hDQoNClBhcmEgbGEgb2J0ZW5jacOzbiBkZSBpbmZvcm1hY2nDs24gZGUgbGEgaGlzdG9yaWEgZGUgbGEgZjEgc2UgaGEgdXNhZG8gW2VzdGFdKGh0dHBzOi8vZXMud2lraXBlZGlhLm9yZy93aWtpL0bDs3JtdWxhXzEpIHDDoWdpbmEgd2ViLiAgDQoNCkxvcyBkYXRvcyBhIHBhcnRpciBkZSBsb3MgY3VhbGVzIHNlIGhhIGVsYWJvcmFkbyBlbCBkZiBkZSBtdWVydGVzIHNlIGhhbiBvYnRlbmlkbyBkZSBbZXN0YV0oaHR0cHM6Ly9lcy53aWtpcGVkaWEub3JnL3dpa2kvQW5leG86TXVlcnRlc19lbl9Gw7NybXVsYV8xKSBww6FnaW5hIHdlYi4gICAgDQoNClBhcmEgbGEgb2J0ZW5jacOzbiBkZSBsb3MgZGF0b3MgZGUgbGFzICBhdWRpZW5jaWFzIHNlIGhhbiB1dGlsaXphZG8gdGFudG8gW2VzdGFdKGh0dHBzOi8vd3d3LnRoZWJlc3RmMS5lcy9hbmFsaXNpcy1hc2ktaGFuLWV2b2x1Y2lvbmFkby1sYXMtYXVkaWVuY2lhcy1lbi1lc3BhbmEtZGVzZGUtbGEtMi1hLW1vdmlzdGFyLWYxLykgcMOhZ2luYSB3ZWIgLCBjb21vIFtlc3RlXShodHRwczovL3R3aXR0ZXIuY29tL01lZEYxb3NUVi9zdGF0dXMvMTM3NjQ2MjgzNDg0MjkyMzAwOCkgcG9zdCBkZSB0d2l0dGVyLiAgIA0KDQpQYXJhIGxhIGVsYWJvcmFjacOzbiBkZWwgYXBhcnRhZG8gZGUgRmVybmFuZG8gQWxvbnNvIHNlIGhhbiB1dGlsaXphZG8gbGFzIHNpZ3VpZW50ZXMgcMOhZ2luYXMgd2ViOiBbZXN0YV0oaHR0cHM6Ly9lcy53aWtpcGVkaWEub3JnL3dpa2kvRmVybmFuZG9fQWxvbnNvKSB5IFtlc3RhXShodHRwczovL2FzLmNvbS9tb3Rvci8yMDIxLzAzLzI0L3JlcG9ydGFqZXMvMTYxNjU4OTA4Nl8yODIwOTguaHRtbCkuICAgDQoNCg==